CQOI2016 K远点对
2016-04-13 16:32
190 查看
大意:求平面上k远点对
很有意思的一道题,凸包+旋转卡壳。
只会写平面上最远点对,现在要求平面上k远点对,那么总思路就是把k远点对转成最远点对。
当求到现在的最远点对(point1,point2)后,若不加处理,下次若继续求最远点对,一定还是(point1,point2),这不是我们想要的,故,要删除这个点对。删后再求最远点对,那么就是次远点对了,以此处理,最终会求得k远点对。那么问题就是删除操作,一个点对由两个点组成,任意删除一个点,这个点对将不存在,我们现在要考虑删除哪个点,我使用的极角排序,正常时候,每次凸包+卡壳的时间其实是O(nlogn+n),logn 是极角排序所带来的,从范围来看,这道题O(kn)是最合理的,显然,每次求最远点对,我不能极角排序,所以,我们要固定编号为1的点(我的代码里是y坐标最小的点中x坐标最小的)。那么删除的时候,就删除标号大的一个点,即为point2。删点的时候,考虑将会带来哪些影响,显然,图中现在存在的点和point2的距离将因为删点永远不会被后面计算到,那么我们就暴力枚举图中剩下的点,求出他们与point2的距离,保存下来,这样,就可以放心地删掉这个点了。最后的部分就是对于那些保存下来的点对距离的处理。每一次删点,理论上最多会有n个点对距离需要保存,设一个Ans[]数组,Ans[i]保存的是前面的计算过程中,第i远点对距离,所以在要保留点对的时候,如果这个距离dis小于当前的Ans[k]就没有必要保存了,每次弄完,把Ans[]排一遍,保存最大的k个,如果某一次没有任何点对距离大于Ans[k],那么break,因为当前平面上最远点已经无法更新Ans[]了,Ans[k]即为所求。代码如下。
!!!!!!!!!!!!!(PS:考试的时候我看数据肯定是n>k,就按n>k写的。。。。。。。。)
!!!!!!!!!!!!!(PS:Ans[]数组的处理其实是带log n的(懒得写堆了。。。。。。。))
很有意思的一道题,凸包+旋转卡壳。
只会写平面上最远点对,现在要求平面上k远点对,那么总思路就是把k远点对转成最远点对。
当求到现在的最远点对(point1,point2)后,若不加处理,下次若继续求最远点对,一定还是(point1,point2),这不是我们想要的,故,要删除这个点对。删后再求最远点对,那么就是次远点对了,以此处理,最终会求得k远点对。那么问题就是删除操作,一个点对由两个点组成,任意删除一个点,这个点对将不存在,我们现在要考虑删除哪个点,我使用的极角排序,正常时候,每次凸包+卡壳的时间其实是O(nlogn+n),logn 是极角排序所带来的,从范围来看,这道题O(kn)是最合理的,显然,每次求最远点对,我不能极角排序,所以,我们要固定编号为1的点(我的代码里是y坐标最小的点中x坐标最小的)。那么删除的时候,就删除标号大的一个点,即为point2。删点的时候,考虑将会带来哪些影响,显然,图中现在存在的点和point2的距离将因为删点永远不会被后面计算到,那么我们就暴力枚举图中剩下的点,求出他们与point2的距离,保存下来,这样,就可以放心地删掉这个点了。最后的部分就是对于那些保存下来的点对距离的处理。每一次删点,理论上最多会有n个点对距离需要保存,设一个Ans[]数组,Ans[i]保存的是前面的计算过程中,第i远点对距离,所以在要保留点对的时候,如果这个距离dis小于当前的Ans[k]就没有必要保存了,每次弄完,把Ans[]排一遍,保存最大的k个,如果某一次没有任何点对距离大于Ans[k],那么break,因为当前平面上最远点已经无法更新Ans[]了,Ans[k]即为所求。代码如下。
!!!!!!!!!!!!!(PS:考试的时候我看数据肯定是n>k,就按n>k写的。。。。。。。。)
!!!!!!!!!!!!!(PS:Ans[]数组的处理其实是带log n的(懒得写堆了。。。。。。。))
#include<iostream> #include<iomanip> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; const double Eps=1e-10; const LL N=200005LL,INF=100000000000000000LL; struct point{LL x,y,i;double ag;}a ,p ; LL n,m,Ans ; bool vst ; LL Dis(point p1,point p2) { LL x=p1.x-p2.x,y=p1.y-p2.y; return x*x+y*y; } LL Cross(point p1,point p2,point p3) { return (p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y); } bool cmp(const point p1,const point p2) { if(fabs(p1.ag-p2.ag)<Eps)return Dis(a[1],p1)<Dis(a[1],p2); return p1.ag<p2.ag; } void Init() { scanf("%lld%lld",&n,&m); LL i,j,k; for(i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].y); LL Minx=INF,Miny=INF; for(i=1;i<=n;i++) if(a[i].y<Miny||(a[i].y==Miny&&a[i].x<Minx)) { Miny=a[i].y;Minx=a[i].x;k=i; } swap(a[1],a[k]); for(i=2;i<=n;i++)a[i].ag=atan2(a[i].y-a[1].y,a[i].x-a[1].x); sort(a+2,a+n+1,cmp); for(i=1;i<=n;i++)a[i].i=i; } bool cmp2(const LL x,const LL y){return x>y;} void Solve() { LL ti,i,j,k,x,y,top,num=0,dis; Ans[0]=-1; for(ti=1;ti<=m;ti++) { top=0; for(i=1;i<=n;i++) { if(vst[a[i].i])continue; while(top>=2&&Cross(p[top],a[i],p[top-1])<=0)top--; p[++top]=a[i]; } dis=0; p[0]=p[top];p[top+1]=p[1]; j=1; for(i=1;i<=top;i++) { while(Dis(p[i],p[j])<=Dis(p[i],p[(j+1)%top]))j=(j+1)%top; if(Dis(p[i],p[j])>dis) { dis=Dis(p[i],p[j]); x=p[i].i;y=p[j].i; } } if(x>y)swap(x,y); vst[y]=1; k=0; for(i=1;i<=n;i++) { if(vst[i])continue; if(Dis(a[y],a[i])>Ans[num]) { k++; Ans[num+k]=Dis(a[y],a[i]); } } if(!k)break; sort(Ans+1,Ans+num+k+1,cmp2); num=min(m,num+k); } printf("%lld",Ans[m]); } int main() { Init(); Solve(); return 0; }
相关文章推荐
- 算法的时间复杂度取决于:
- Swift 关键字
- Material Design recyclerview+floatingactionbutto实现联动的效果
- jvm垃圾回收
- bzoj 1818(树状数组)
- vsftpd的配置 (Linux下的ftp服务器)
- 【iOS】iOS main() 简介
- push to deploy
- 专门查看阻塞和死锁情况以及引起的SQL语句,你可以创建后,直接运行之。
- class、classLoader的getResourceAsStream的区别
- 微信开发<二>接收普通消息、自动回复
- Tomacat7启动报错-org.apache.catalina.deploy.WebXml addFilter
- 校招真题-其他-左右最值最大差
- HTML5 参考手册(全局属性)
- 利用java反射机制,实现对类的私有变量和私有方法的访问
- 巧用array_map()和array_reduce()替代foreach循环
- CF319D Have You Ever Heard About The World? 二分Hash判断可行解
- android设计模式之observer
- tcp/ip详解笔记001——概述
- LeetCode *** 11. Container With Most Water