题目描述

已知平面内 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)$
  •  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 }
    bzoj4520(kdt)

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-16
  • 2022-12-23
  • 2022-12-23
  • 2021-11-21
  • 2022-01-06
猜你喜欢
  • 2021-10-07
  • 2021-05-15
  • 2021-05-19
  • 2021-06-02
  • 2021-07-11
相关资源
相似解决方案