[APIO2018]选圆圈(KD-Tree)
Posted HocRiser
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[APIO2018]选圆圈(KD-Tree)相关的知识,希望对你有一定的参考价值。
题意:给你n个圆,每次选择半径最大的,将它和与它相交的圆全部删去,输出每个圆是在哪次被删的。
KD树模板题。用一个矩形框住这个圆,就可以直接剪枝了。为了防止被卡可以将点旋转一个角度,为了保险还可以多转几个角度。
1 #include<cmath> 2 #include<cstdio> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 typedef double db; 6 using namespace std; 7 8 const int N=300010; 9 const db inf=1e20,eps=1e-3,alpha=acos(-1)/3; 10 int n,rt,ans[N]; 11 db x,y,r; 12 struct P{ db x,y,r; int id; }cur,a[N]; 13 struct Tr{ int ls,rs; db x1,y1,x2,y2; P c; }T[N]; 14 15 bool cmpx(const P &a,const P &b){ return a.x<b.x; } 16 bool cmpy(const P &a,const P &b){ return a.y<b.y; } 17 bool cmpr(const P &a,const P &b){ return (a.r==b.r) ? a.id<b.id : a.r>b.r; } 18 19 void F(int x,int y){ 20 T[x].x1=min(T[x].x1,T[y].x1); T[x].x2=max(T[x].x2,T[y].x2); 21 T[x].y1=min(T[x].y1,T[y].y1); T[x].y2=max(T[x].y2,T[y].y2); 22 } 23 24 void upd(int x){ 25 if (ans[T[x].c.id]) T[x].x1=T[x].y1=inf,T[x].x2=T[x].y2=-inf; 26 else{ 27 T[x].x1=T[x].c.x-T[x].c.r; T[x].x2=T[x].c.x+T[x].c.r; 28 T[x].y1=T[x].c.y-T[x].c.r; T[x].y2=T[x].c.y+T[x].c.r; 29 } 30 if (T[x].ls) F(x,T[x].ls); 31 if (T[x].rs) F(x,T[x].rs); 32 } 33 34 int build(int l,int r,int k){ 35 if (l>r) return 0; 36 int mid=(l+r)>>1; nth_element(a+l,a+mid,a+r+1,k?cmpy:cmpx); 37 T[mid].c=a[mid]; 38 T[mid].ls=build(l,mid-1,k^1); T[mid].rs=build(mid+1,r,k^1); 39 upd(mid); return mid; 40 } 41 42 db sqr(db x){ return x*x; } 43 bool Out(int x){ return (T[x].x2<cur.x-cur.r-eps) || (T[x].x1>cur.x+cur.r+eps) || (T[x].y2<cur.y-cur.r-eps) || (T[x].y1>cur.y+cur.r+eps); } 44 bool chk(P &a){ return sqr(a.x-cur.x)+sqr(a.y-cur.y)<=sqr(a.r+cur.r)+eps; } 45 46 void que(int x){ 47 if (Out(x)) return; 48 if (!ans[T[x].c.id] && chk(T[x].c)) ans[T[x].c.id]=cur.id; 49 if (T[x].ls) que(T[x].ls); 50 if (T[x].rs) que(T[x].rs); 51 } 52 53 int main(){ 54 freopen("apiob.in","r",stdin); 55 freopen("apiob.out","w",stdout); 56 scanf("%d",&n); 57 rep(i,1,n) 58 scanf("%lf%lf%lf",&x,&y,&r),a[i]=(P){x*cos(alpha)+y*sin(alpha),y*cos(alpha)-x*sin(alpha),r,i}; 59 rt=build(1,n,0); sort(a+1,a+n+1,cmpr); 60 rep(i,1,n) if (!ans[a[i].id]) ans[a[i].id]=a[i].id,cur=a[i],que(rt); 61 rep(i,1,n) printf("%d ",ans[i]); puts(""); 62 return 0; 63 }
以上是关于[APIO2018]选圆圈(KD-Tree)的主要内容,如果未能解决你的问题,请参考以下文章