$$AVICII$$

P7883 平面最近点对(加强加强版)

首先想到kd-tree,复杂度主要看剪枝

另一种做法也是分治,先以x排序,然后分治求区间答案(这个答案是小于当前已经得到的答案)

那么可以先对分治排序y,然后找到所有与中心线距离小于当前答案的点

这些点已经以y的顺序排好,所以对于i往后枚举j,当点i和点j的纵坐标距离大于等于当前答案就break

总结来说就是两层剪枝

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=4e5+17;
 4 int n;
 5 struct vd{
 6     double x,y;
 7     friend bool operator <(const vd a,const vd b){
 8         return a.x<b.x;
 9     }
10 }dot[MAXN];
11 double ans=1e9;
12 long long res;
13 inline void upd(vd a,vd b){
14     long long t=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
15     if(ans>sqrt(1.0*t))ans=sqrt(t),res=t;
16     return ;
17 }
18 vd que[MAXN];
19 void fenzhi(int l,int r){
20     if(l==r)return ;
21     int mid=l+r>>1;
22     double mid_x=dot[mid].x;
23     fenzhi(l,mid),fenzhi(mid+1,r);
24     int pl=l,pr=mid+1,p=l;
25     while(pl<=mid&&pr<=r){
26         if(dot[pl].y<=dot[pr].y)que[p++]=dot[pl++];
27         else que[p++]=dot[pr++];
28     }
29     while(pl<=mid)que[p++]=dot[pl++];
30     while(pr<=r)que[p++]=dot[pr++];
31     for(int i=l;i<=r;++i)dot[i]=que[i];
32 //    cout<<l<<" "<<r<<endl;
33 //    for(int i=l;i<=r;++i){
34 //        cout<<i<<" "<<dot[i].x<<" "<<dot[i].y<<endl;
35 //    }
36     p=l;
37     for(int i=l;i<=r;++i)
38         if(fabs(dot[i].x-mid_x)<ans)
39             que[p++]=dot[i];
40     for(int i=l;i<p;++i)
41         for(int j=i+1;fabs(que[i].y-que[j].y)<ans&&j<p;++j)
42             upd(que[i],que[j]);
43     return ;
44 }
45 int main(){
46     scanf("%d",&n);
47     for(int i=1;i<=n;++i)scanf("%lf%lf",&dot[i].x,&dot[i].y);
48     sort(dot+1,dot+n+1);
49     fenzhi(1,n);
50     printf("%lld",res);
51     return 0;
52 }
View Code

 

posted @ 2021-12-08 20:25  bootpuss  阅读(69)  评论(0编辑  收藏  举报