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 }