题目描述
已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。
输入格式
输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点
的坐标。1 < = N < = 100000, 1 < = K < = 100, K < = N*(N−1)/2 , 0 < = X, Y < 2^31。
输出格式
输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。
- 注意只需要保证最大的k个值都被找到就可以确定答案了;
- 旋转卡壳做法:
- 平面最近点对可以通过求出凸包之后(特判一下一条直线)卡壳得到;
- 这样求$min(n-1,k)$次最远点对;
- 每求一次,就将求出的点对删掉,将和它们相关的距离放进小顶堆中,多于$k$个就丢掉最小值;
- 答案就是堆顶;
- 当做到最远距离已经<=堆顶时就可以break了;
- 复杂度:$O(NlogN+NKlogK)$
-
bzoj4520(kdt)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=100010; 5 int n,m,WD,mn[N][2],mx[N][2],ch[N][2],rt; 6 struct P{ 7 int x,y; 8 P(int _x=0,int _y=0):x(_x),y(_y){}; 9 P operator -(const P&a)const{return P(x-a.x,y-a.y);} 10 bool operator <(const P&a)const{return WD?y<a.y:x<a.x;} 11 }p[N],q; 12 priority_queue<ll,vector<ll>,greater<ll> >ans; 13 ll len(P a){return (ll)a.x*a.x+(ll)a.y*a.y;} 14 void build(int&k,int l,int r,int d){ 15 k=(l+r)>>1; 16 WD=d;nth_element(p+l,p+k,p+r+1); 17 mn[k][0]=mx[k][0]=p[k].x; 18 mn[k][1]=mx[k][1]=p[k].y; 19 if(l<k){build(ch[k][0],l,k-1,d^1);} 20 if(k<r){build(ch[k][1],k+1,r,d^1);} 21 for(int i=0;i<2;++i)if(ch[k][i]){ 22 int t = ch[k][i]; 23 mn[k][0]=min(mn[t][0],mn[k][0]); 24 mn[k][1]=min(mn[t][1],mn[k][1]); 25 mx[k][0]=max(mx[t][0],mx[k][0]); 26 mx[k][1]=max(mx[t][1],mx[k][1]); 27 } 28 } 29 inline ll sqr(int x){return (ll)x*x;} 30 inline ll cal(int k){ 31 if(!k)return 0; 32 return max(sqr(q.x-mn[k][0]),sqr(q.x-mx[k][0])) + max(sqr(q.y-mn[k][1]),sqr(q.y-mx[k][1])) ; 33 } 34 void query(int k){ 35 ll tmp = len(p[k]-q); 36 // printf("%lld\n",tmp); 37 if(tmp>ans.top())ans.pop(),ans.push(tmp); 38 ll tl = cal(ch[k][0]), tr = cal(ch[k][1]); 39 if(tl>tr){ 40 if(tl>ans.top())query(ch[k][0]); 41 if(tr>ans.top())query(ch[k][1]); 42 }else{ 43 if(tr>ans.top())query(ch[k][1]); 44 if(tl>ans.top())query(ch[k][0]); 45 } 46 } 47 int main(){ 48 #ifndef ONLINE_JUDGE 49 freopen("T2.in","r",stdin); 50 freopen("T2.out","w",stdout); 51 #endif 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;++i)scanf("%d%d",&p[i].x,&p[i].y); 54 for(int i=1;i<=m*2;++i)ans.push(0); 55 build(rt,1,n,0); 56 for(int i=1;i<=n;++i){q=p[i];query(rt);} 57 cout<<ans.top()<<endl; 58 return 0; 59 }