Bzoj3663/4660 CrazyRabbit
题意:给定平面上一个圆和一堆圆外的点,要求选出尽可能多的点使得它们之间两两连线都不和圆相交。保证任意两点连线不和圆相切。点数<=2000
这题是很久以前在某张课件上看见的。看了题解还搞了三小时,联赛滚粗既视感。
有个结论我是直接看的课件:“点和点连线不与圆相交”对应“这两个点所对的圆上的极角序区间相交但不相互包含”,并不会证,画画图好像是对的。
在直线上选择一些两两相交且不包含的区间[L1,R1],[L2,R2],[L3,R3]….,按左端点排序之后,必然有L1<L2<L3….<Ln<R1<…<Rn,然后课件让我枚举第一个区间是谁,按左端点排序后对右端点跑LIS,O(N^2logN). 这里认为左端点可以在圆上所在区间里逆时针走到所在区间的右端点。
但是我写了一发过不了样例,因为在一个环上选一些两两相交不重合的区间,并不一定存在一个区间把其他区间的左端点都包含起来,比如说把圆三等分成三个区间,再把每个区间稍微左右延长一点点。
懵逼…不过仔细观察,发现这个时候如果选了一个起始区间直接跑LIS,出错时一定是有一个区间左端点不被选中的起始区间包含,但这个区间的右端点绕回了起始区间。那么我们把这个区间变成它在圆上的补区间,好像就挺对的。
所以我们把“左端点不在起始区间但右端点在起始区间内”的区间变成它的补区间,也就是把左右端点交换一下,然后跑LIS就A了。这么做的原理是假如区间A和区间B相交且不包含,那么区间A的补区间也一定和区间B相交且不包含。但是,区间A,B都取补区间后不一定相交且不包含。所以跑完一遍LIS还得把交换过的左右端点恢复回去,实现时我写了一发时间戳标记每个区间是否被交换。
PS. 极角序区间预处理的时候注意所求极角的范围。
- /**************************************************************
- Problem: 4660
- User: liu_runda
- Language: C++
- Result: Accepted
- Time:5540 ms
- Memory:944 kb
- ****************************************************************/
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #include<cstring>
- using namespace std;
- const int maxn=2005;
- const double pi=3.14159265;
- struct point{
- double x,y;
- void read(){
- scanf("%lf %lf",&x,&y);
- }
- point(){
- }
- point(double _x,double _y){
- x=_x;y=_y;
- }
- point operator-(const point &B)const{
- return point(x-B.x,y-B.y);
- }
- }P[maxn];
- double l[maxn],r[maxn];
- double angle(point A){
- return atan2(A.y,A.x);
- }
- int seq[maxn];int tot=0;
- bool betw(double l,double r,double x){
- if(l<r){
- return l<x&&x<r;
- }else{
- return (x>l)||(x<r);
- }
- }
- bool cmp1(const int &a,const int &b){
- return l[a]<l[b];
- }
- double curl,curr;
- bool cmp2(const int &a,const int &b){
- if(a>curl&&b>curl)return l[a]<l[b];
- else if(a<curr&&b<curr)return l[a]<l[b];
- else return l[a]>curl;
- }
- double m[maxn];
- double _r[maxn];
- int lis(){
- memset(m,0x42,sizeof(m));
- m[0]=-1e30;
- for(int i=1;i<=tot;++i){
- _r[i]=r[seq[i]]-curl;
- if(_r[i]<0)_r[i]+=2*pi;
- }/*
- for(int i=1;i<=tot;++i)printf("%.2f ",_r[i]);
- printf("\n");
- for(int i=1;i<=tot;++i){
- printf("%.2f %.2f\n",l[seq[i]],r[seq[i]]);
- }*/
- int ans=0;double *pt;
- for(int i=1;i<=tot;++i){
- pt=upper_bound(m,m+tot+1,_r[i]);
- if((pt-m)>ans)ans=pt-m;
- *pt=_r[i];
- }
- return ans;
- }
- int T;
- int mark[maxn];
- int main(){
- // freopen("4660.in","r",stdin);
- // freopen("4660.out","w",stdout);
- int n,R;
- scanf("%d%d",&n,&R);
- for(int i=1;i<=n;++i)P[i].read();
- double tmp,delta;
- for(int i=1;i<=n;++i){
- tmp=angle(P[i]);delta=fabs(acos(R/sqrt(P[i].x*P[i].x+P[i].y*P[i].y)));
- // printf("%.2f %.2f\n",tmp,delta);
- l[i]=tmp-delta;r[i]=tmp+delta;
- if(l[i]<-pi)l[i]+=pi*2;
- if(r[i]>pi)r[i]-=pi*2;
- }//printf("\n");
- /* for(int i=1;i<=n;++i){
- printf("%.2f %.2f\n",l[i],r[i]);
- }//while(1);
- printf("\n");*/
- int ans=0,curans;
- for(int i=1;i<=n;++i){//枚举起点
- tot=0;
- ++T;
- seq[++tot]=i;
- for(int j=1;j<=n;++j){
- if(i!=j&&betw(l[i],r[i],l[j])&&!betw(l[i],r[i],r[j]))seq[++tot]=j;
- else if(i!=j&&betw(l[i],r[i],r[j])&&!betw(l[i],r[i],l[j])){
- swap(l[j],r[j]);seq[++tot]=j;
- mark[j]=T;
- }
- }
- curl=l[i];curr=r[i];
- if(l[i]<r[i])sort(seq+1,seq+tot+1,cmp1);
- else sort(seq+1,seq+tot+1,cmp2);
- curans=lis();
- if(curans>ans)ans=curans;
- for(int j=1;j<=tot;++j){
- if(mark[j]==T)swap(l[j],r[j]);
- }
- }
- printf("%d\n",ans);//while(1);
- return 0;
- }
- /*
- 5 8
- -7 20
- 10 80
- -7 26
- -13 79
- 11 81
- */
Bzoj3663/4660 CrazyRabbit的更多相关文章
- 三倍经验——bzoj3663、4660、4206 Crazy Rabbit/最大团
题目描述: 3663 4660 4206 题解: 第一眼:不成立的互相连边,然后用网络流求解无向图最小点覆盖! 好吧我不会. 正解: 每个点对应圆上的一段圆弧,长这样: 设对应圆弧$(l,r)$. 若 ...
- bzoj 4660 Crazy Rabbit——LIS解决“相交”限制的思想
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4660 想到一个点可以用它与圆的两个切点表示.并想到可以把切点极角排序,那么就变成环上的一些区 ...
- bzoj3663/4660CrazyRabbit && bzoj4206最大团
题意 给出平面上N个点的坐标,和一个半径为R的圆心在原点的圆.对于两个点,它们之间有连边,当且仅当它们的连线与圆不相交.求此图的最大团. 点数<=2000,坐标的绝对值和半径<=5000. ...
- bzoj 3768: spoj 4660 Binary palindrome二进制回文串
Description 给定k个长度不超过L的01串,求有多少长度为n的01串S满足: 1.该串是回文串 2.该串不存在两个不重叠的子串,在给定的k个串中. 即不存在a<=b<c<= ...
- 2018.10.30 一题 洛谷4660/bzoj1168 [BalticOI 2008]手套——思路!问题转化与抽象!+单调栈
题目:https://www.luogu.org/problemnew/show/P4660 https://www.lydsy.com/JudgeOnline/problem.php?id=1168 ...
- bzoj3663
几何+lis 很巧妙.直接做很困难,那么我们转化一下,把每个点能看见的圆弧画出来.只有这些圆弧相交时才满足条件. 那么也就是找出圆上尽量多两两相交的区间. 所以我们先按左端点极角排序,然后固定一个必须 ...
- [Keras] Develop Neural Network With Keras Step-By-Step
简单地训练一个四层全连接网络. Ref: http://machinelearningmastery.com/tutorial-first-neural-network-python-keras/ 1 ...
- EChart数据的异步加载和更新
ECharts是国内开发一款图标插件,在网页中我们经常要用到图标显示,直接引用十分方便. 直接到ECharts主页调用插件 <!DOCTYPE html> <html style=& ...
- 通用js地址选择器
用js实现通用的地址选择器,省份,城市,地区自动关联更新 点击下面查看详细代码: http://runjs.cn/code/s8sqkhcv 关键地址库代码: var addr_arr = new A ...
随机推荐
- [Azure] 使用 Azure 快速搭建 Redis 服务器
Redis相信玩开源,大数据的朋友们并不陌生,大家最熟悉的使用者就是新浪微博,微博的整体数据缓存都是基于Redis的,而新浪对Redis的使用也非常深,据说是一组64G内存的Redis集群.前段时间我 ...
- Iptables 报错Couldn't load target `ACCET':/lib64/xtables/libipt_ACCET.so: cannot open shared object file
[root@xxxx ~]# /etc/init.d/iptables restart iptables: Setting chains to policy ACCEPT: filter nat [ ...
- express:webpack dev-server开发中如何调用后端服务器的接口?
开发环境: 前端:webpack + vue + vue-resource,基于如下模板创建的开发环境: https://github.com/vuejs-templates/webpack ...
- 多态、GC、Java数据类型
多态 一.java中实现多态的机制是什么? 靠的是: 父类定义的引用变量可以指向子类的实例对象,或者接口定义的引用变量可以指向具体实现类的实例对象 而程序调用的方法,在运行期才动态绑定, 它就是引用变 ...
- 【一】我眼中的FeatureLayer
1.来源 MapService 或者 FeatureService(10.0后)中的一个图层 Tabel 动态空间 2.使用 符号化 首先看下FLyr的继承关系:FeatureLayer Graph ...
- 继续node爬虫 — 百行代码自制自动AC机器人日解千题攻占HDOJ
前言 不说话,先猛戳 Ranklist 看我排名. 这是用 node 自动刷题大概半天的 "战绩",本文就来为大家简单讲解下如何用 node 做一个 "自动AC机&quo ...
- EF 相见恨晚的Attach方法
一个偶然的机会,让我注意了EF 的Attach方法,于是深入了解让我大吃一惊 在我所参与的项目中所有的更新操作与删除操作都是把原对象加载出来后,再做处理,然后再保存到数据库,这样的操作不缺点在于每一次 ...
- ASP.NET MVC 多语言实现技巧 最简、最易维护和最快速开发
说说传统做法的缺点 1.做过多语言的都知道这玩意儿太花时间 2.多语言架构一般使用资源文件.XML或者存储数据库来实现.这样就在一定程序上降低了性能 3.页面的可读性变差,需要和资源文件进行来回切换 ...
- js的Array的map和sort实现方法
Array.prototype.mapA = function(fun /*, thisp*/) { var len = this.length; if (typeof fun != "fu ...
- bloom filter
Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员. 结 构 二进制 召回率 ...