[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)的主要内容,如果未能解决你的问题,请参考以下文章

[loj2586]选圆圈

APIO2018SB滚粗记

p1552 [APIO2012]派遣

3624: [Apio2008]免费道路

APIO 2016

APIO2018 爆零滚粗记