根据圆心建一棵kd-tree,然后模拟题目的过程,考虑搜索一个圆
剪枝:如果[与包含该子树内所有圆的最小矩形]都不相交就退出
然而这样的理论复杂度是o(n^2),所以会被出题人卡了
但是如果将坐标系旋转45度,对于(x,y),变为$((x-y)/\sqrt{2},(x+y)/\sqrt{2})$
然后因为可能相切,精度要求高,eps大约要取1e-3
View Code
1 #include2 using namespace std; 3 #define N 3000005 4 #define k (l+r>>1) 5 #define s (sqrt(2)) 6 #define eps (1e-3) 7 #define sqr(x) (1LL*(x)*(x)) 8 int n,t,id[N],ans[N],ls[N],rs[N]; 9 struct P{ 10 double x,y; 11 }mn[N],mx[N]; 12 struct ji{ 13 int r,id; 14 P a; 15 bool operator < (const ji &p){ 16 if (t)return a.x<p.a.x; 17 return a.y<p.a.y; 18 } 19 }a[N]; 20 bool cmp(int x,int y){ 21 return (a[x].r>a[y].r)||(a[x].r==a[y].r)&&(a[x].id<a[y].id); 22 } 23 P rotate(P x){ 24 return P{(x.x-x.y)/s,(x.x+x.y)/s}; 25 } 26 double dis(P x,P y){ 27 return sqr(x.x-y.x)+sqr(x.y-y.y); 28 } 29 double calc(int t,P x){ 30 P y; 31 if (x.x mn[t].x; 32 else 33 if (x.x<=mx[t].x)y.x=x.x; 34 else y.x=mx[t].x; 35 if (x.y mn[t].y; 36 else 37 if (x.y<=mx[t].y)y.y=x.y; 38 else y.y=mx[t].y; 39 return dis(x,y); 40 } 41 void up(int l,int r){ 42 mn[k].x=min(mn[ls[k]].x,mn[rs[k]].x); 43 mn[k].y=min(mn[ls[k]].y,mn[rs[k]].y); 44 mx[k].x=max(mx[ls[k]].x,mx[rs[k]].x); 45 mx[k].y=max(mx[ls[k]].y,mx[rs[k]].y); 46 if (ans[a[k].id])return; 47 mn[k].x=min(mn[k].x,a[k].a.x-a[k].r); 48 mn[k].y=min(mn[k].y,a[k].a.y-a[k].r); 49 mx[k].x=max(mx[k].x,a[k].a.x+a[k].r); 50 mx[k].y=max(mx[k].y,a[k].a.y+a[k].r); 51 } 52 int build(int l,int r,int p){ 53 if (l>r)return 0; 54 t=p; 55 nth_element(a+l,a+k,a+r+1); 56 ls[k]=build(l,k-1,p^1); 57 rs[k]=build(k+1,r,p^1); 58 up(l,r); 59 return k; 60 } 61 void query(int l,int r,int x){ 62 if (l>r)return; 63 if (calc(k,a[x].a)>sqr(a[x].r)+eps)return; 64 if ((!ans[a[k].id])&&(dis(a[x].a,a[k].a)<=sqr(a[x].r+a[k].r)+eps))ans[a[k].id]=a[x].id; 65 query(l,k-1,x); 66 query(k+1,r,x); 67 up(l,r); 68 } 69 int main(){ 70 scanf("%d",&n); 71 for(int i=1;i<=n;i++){ 72 scanf("%lf%lf%d",&a[i].a.x,&a[i].a.y,&a[i].r); 73 a[i].a=rotate(a[i].a); 74 a[i].id=id[i]=i; 75 } 76 mn[0].x=mn[0].y=2e9+1; 77 mx[0].x=mx[0].y=-2e9-1; 78 build(1,n,0); 79 sort(id+1,id+n+1,cmp); 80 for(int i=1;i<=n;i++) 81 if (!ans[a[id[i]].id])query(1,n,id[i]); 82 for(int i=1;i<=n;i++)printf("%d ",ans[i]); 83 }