LOJ#2586. 「APIO2018」选圆圈 KDtree+剪枝
直接做的话洛谷上能过,LOJ 上要在开始的时候把所有点都旋转一个特定的角度来保证随机性.
code:
#include <bits/stdc++.h> #define N 300007 #define ll long long #define inf 1000000000 #define eps 5e-2 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int d,n,ans[N]; double sqr(double x) { return x*x; } struct data { int ch[2],si,id; double p[2],mi[2],ma[2],cmi[2],cma[2],r; bool operator<(const data b) const { return p[d]==b.p[d]?p[d^1]<b.p[d^1]:p[d]<b.p[d]; } int out(data b) { int flag=0; for(int i=0;i<2;++i) if(mi[i]>b.ma[i]||ma[i]<b.mi[i]) flag=1; return flag; } int check(data b) { double dis1=sqr(p[0]-b.p[0])+sqr(p[1]-b.p[1]); double dis2=sqr(r+b.r); return dis2-dis1>=-eps; } }s[N]; void pushup(int x,int y) { for(int i=0;i<2;++i) { s[x].mi[i]=min(s[x].mi[i],s[y].mi[i]); s[x].ma[i]=max(s[x].ma[i],s[y].ma[i]); } } int build(int l,int r,int o) { int mid=(l+r)>>1; d=o,nth_element(s+l,s+mid,s+1+r),s[mid].si=1; if(mid>l) { s[mid].ch[0]=build(l,mid-1,o^1); pushup(mid,s[mid].ch[0]),s[mid].si+=s[s[mid].ch[0]].si; } if(r>mid) { s[mid].ch[1]=build(mid+1,r,o^1); pushup(mid,s[mid].ch[1]),s[mid].si+=s[s[mid].ch[1]].si; } return mid; } struct cir { double x,y,r; int id; cir(double x=0,double y=0,int id=0,double r=0):x(x),y(y),id(id),r(r){} bool operator<(const cir b) const { return r==b.r?id<b.id:r>b.r; } }c[N]; int query(int x,data b,int fa) { if(!s[x].si||s[x].out(b)) return 0; int tp=0; if(!ans[s[x].id]&&s[x].check(b)) { ans[s[x].id]=fa,tp=1; s[x].mi[0]=s[x].mi[1]=s[x].cmi[0]=s[x].cmi[1]=inf; s[x].ma[0]=s[x].ma[1]=s[x].cma[0]=s[x].cma[1]=-inf; } for(int i=0;i<2;++i) s[x].mi[i]=s[x].cmi[i],s[x].ma[i]=s[x].cma[i]; if(s[x].ch[0]) tp+=query(s[x].ch[0],b,fa),pushup(x,s[x].ch[0]); if(s[x].ch[1]) tp+=query(s[x].ch[1],b,fa),pushup(x,s[x].ch[1]); s[x].si-=tp; return tp; } const double sina=sqrt(2)/2; const double cosa=sqrt(2)/2; int main() { // setIO("input"); scanf("%d",&n); for(int i=1;i<=n;++i) { double a,b,r,x,y; scanf("%lf%lf%lf",&a,&b,&r); x=a*cosa-b*sina; y=a*sina+b*cosa; s[i].cmi[0]=s[i].mi[0]=x-r; s[i].cma[0]=s[i].ma[0]=x+r; s[i].cmi[1]=s[i].mi[1]=y-r; s[i].cma[1]=s[i].ma[1]=y+r; s[i].p[0]=x,s[i].p[1]=y,s[i].id=i,s[i].r=r; c[i]=cir(x,y,i,r); } sort(c+1,c+1+n); data tmp; int root=build(1,n,0); for(int i=1;i<=n;++i) { if(!ans[c[i].id]) { tmp.p[0]=c[i].x,tmp.p[1]=c[i].y,tmp.r=c[i].r; tmp.mi[0]=c[i].x-c[i].r,tmp.ma[0]=c[i].x+c[i].r; tmp.mi[1]=c[i].y-c[i].r,tmp.ma[1]=c[i].y+c[i].r; query(root,tmp,c[i].id); } } for(int i=1;i<=n;++i) printf("%d ",ans[i]); return 0; }