【bzoj2961】共点圆 k-d树

更新:此题我的代码设置eps=1e-8会WA,现在改为1e-9貌似T了

此题网上的大部分做法是cdq分治+凸包,然而我觉得太烦了,于是自己口胡了一个k-d树做法:

加入一个圆$(x,y)$,直接在k-d树上加入这个点即可,注意要打rebuild否则会T。

查询一个点$(x_0,y_0)$是否在所有的圆上时:

我们设当前需要判断一个圆$(x,y)$是否覆盖该点,通过简单的分析,可以列出以下式子:

$(x-x_0)^2+(y-y_0)^2≤x_0^2+y_0^2$

我们不妨设$y_0>0$通过简单变式和移项,我们可以得到:

$y \geq -\frac{x_0}{y_0}x+\frac{x_0^2+y_0^2}{2y}$

我们将$ -\frac{x_0}{y_0} $和$ \frac{x_0^2+y_0^2}{2y} $视作常数,得到$y≤kx+b$,这是啥?一个半平面啊!!

问题即转化为了当前k-d树中是否所有点均在该半平面内,直接在k-d树中查询即可(实际上还需要有点思考量的分类讨论)

对于$y_0<0$的情况,部分符号需做些许更改。对于$y_0=0$的情况,需要特殊讨论!!(大概是$x<\frac{x_0}{2}$)

然后就没啦,时间复杂度$O(n log n+n^{1.5})$

PS:千万要记得打y=0的情况(我就被这个卡了很久)

 

  1 #include<bits/stdc++.h>
  2 #define M 500000
  3 #define eps 1e-9
  4 #define INF 1e20
  5 using namespace std;
  6 
  7 #define MFLONG 13000000                                                                          
  8 #define NUM(x) ((48<=x&&x<=57)||x=='-')
  9 char _c[MFLONG],_w[MFLONG]={0};int _ns=0,_nw=0;int _x[30],_ld;
 10 inline void rd(int &_q){int _fu;if(_c[_ns]==0) return;while(!NUM(_c[_ns])) _ns++;if(_c[_ns]=='-') _fu=-1,_ns++;else _fu=1;_q=0;while(NUM(_c[_ns])) _q=_q*10+_c[_ns++]-48;_q=_fu*_q;}
 11 inline void rd(double &X)
 12 {
 13     double x=0,f=1;
 14     for (;_c[_ns]<'0'||_c[_ns]>'9';_ns++) if (_c[_ns]=='-') f=-1;
 15     for (;_c[_ns]>='0'&&_c[_ns]<='9';_ns++) x=x*10+_c[_ns]-'0';
 16     if (_c[_ns]!='.') {X=x*f;return;} _ns++;
 17     for (double hh=0.1;_c[_ns]>='0'&&_c[_ns]<='9';_ns++,hh=hh/10) x+=(_c[_ns]-'0')*hh;
 18     X=x*f;
 19 }
 20 
 21 int D;
 22 struct node{
 23     double max[2],min[2],a[2];
 24     int l,r,siz;
 25     node(){
 26         max[0]=max[1]=a[0]=a[1]=l=r=siz=0;
 27         min[0]=min[1]=INF;
 28     }
 29     void clear(){
 30         max[0]=max[1]=a[0]=a[1]=l=r=siz=0;
 31         min[0]=min[1]=INF;
 32     }
 33     node(double x,double y){
 34         max[0]=max[1]=l=r=siz=0;
 35         min[0]=min[1]=INF;
 36         a[0]=x; a[1]=y;
 37     }
 38     friend bool operator <(node a,node b){return a.a[D]<b.a[D];}
 39 }a[M]; int root=0,use=0,reb=0,rebfa=0,rebd=0;
 40 
 41 void insert(int &x,int fa,int d,node k){
 42     if(!x){x=++use; a[x]=k;}
 43     else{
 44         if(k.a[d]<a[x].a[d]) insert(a[x].l,x,d^1,k);
 45         else insert(a[x].r,x,d^1,k);
 46     }
 47     a[x].siz++; 
 48     a[x].max[0]=max(a[x].max[0],k.a[0]); a[x].min[0]=min(a[x].min[0],k.a[0]);
 49     a[x].max[1]=max(a[x].max[1],k.a[1]); a[x].min[1]=min(a[x].min[1],k.a[1]);
 50     if(max(a[a[x].l].siz,a[a[x].r].siz)>a[x].siz*0.77) reb=x,rebfa=fa,rebd=d;
 51 }
 52 
 53 int id[M]={0},cnt=0;
 54 bool cmp(int x,int y){return a[x]<a[y];}
 55 void bl(int x){if(!x) return;id[++cnt]=x;bl(a[x].l); bl(a[x].r);}
 56 void rebuild(int &x,int l,int r,int d){
 57     if(l>r) {x=0; return;}
 58     int mid=(l+r)>>1; D=d;
 59     nth_element(id+l,id+mid,id+r+1,cmp); x=id[mid]; 
 60     a[x].max[0]=a[x].min[0]=a[x].a[0];
 61     a[x].max[1]=a[x].min[1]=a[x].a[1];
 62     rebuild(a[x].l,l,mid-1,d^1); rebuild(a[x].r,mid+1,r,d^1);
 63     a[x].siz=a[a[x].l].siz+a[a[x].r].siz+1;
 64     for(int i=0;i<2;i++)
 65     a[x].max[i]=max(a[x].max[i],max(a[a[x].l].max[i],a[a[x].r].max[i])),
 66     a[x].min[i]=min(a[x].min[i],min(a[a[x].l].min[i],a[a[x].r].min[i]));
 67 }
 68 void rebuild(){
 69     if(!reb) return;
 70     bl(reb); 
 71     if(!rebfa) rebuild(root,1,cnt,rebd);
 72     else{
 73         if(a[rebfa].l==reb) rebuild(a[rebfa].l,1,cnt,rebd);
 74         else rebuild(a[rebfa].r,1,cnt,rebd);
 75     }
 76     cnt=reb=rebfa=0;
 77 }
 78 
 79 bool queryl(int x,double k,double b){
 80     if(!x) return 1;
 81     if(k>0&&a[x].max[0]*k+b<a[x].min[1]-eps) return 0;
 82     if(k>0&&a[x].min[0]*k+b>=a[x].max[1]) return 1;
 83     if(k>0&&a[x].a[0]*k+b<a[x].a[1]+eps) return 0;
 84     
 85     if(k<=0&&a[x].max[0]*k+b>=a[x].max[1]-eps) return 1;
 86     if(k<=0&&a[x].min[0]*k+b<a[x].min[1]) return 0;
 87     if(k<=0&&!(a[x].a[0]*k+b>a[x].a[1]-eps)) return 0;
 88     
 89     return queryl(a[x].l,k,b)&queryl(a[x].r,k,b);
 90 }
 91 
 92 bool queryr(int x,double k,double b){
 93     if(!x) return 1;
 94     if(k>0&&a[x].max[0]*k+b<a[x].min[1]) return 1;
 95     if(k>0&&a[x].min[0]*k+b>a[x].max[1]-eps) return 0;
 96     if(k>0&&a[x].a[0]*k+b>a[x].a[1]-eps) return 0;
 97     
 98     if(k<=0&&a[x].max[0]*k+b>a[x].max[1]) return 0;
 99     if(k<=0&&a[x].min[0]*k+b<a[x].min[1]+eps) return 1;
100     if(k<=0&&!(a[x].a[0]*k+b<a[x].a[1]+eps)) return 0;
101     
102     return queryr(a[x].l,k,b)&queryr(a[x].r,k,b); 
103 }
104 
105 bool queryx(int x,int k,double l){
106     if(!x) return 1;
107     if(k>0&&l<=a[x].min[0]+eps) return 1;
108     if(k>0&&l>a[x].max[0]-eps) return 0;
109     if(k>0&&l>a[x].a[0]-eps) return 0;
110     
111     if(k<0&&a[x].max[0]-eps<=l) return 1;
112     if(k<0&&l<a[x].min[0]+eps) return 0;
113     if(k<0&&l>a[x].a[0]) return 0;
114     
115     return queryx(a[x].l,k,l)&queryx(a[x].r,k,l); 
116 }
117 
118 int main(){
119     //fread(_c,1,MFLONG,stdin);
120     int n; //rd(n);
121     scanf("%d",&n);
122     while(n--){
123         int op; double x,y; 
124         //rd(op);rd(x);rd(y);
125         scanf("%d%lf%lf",&op,&x,&y);
126         if(op==0){
127             insert(root,0,0,node(x,y));
128             rebuild();
129         }else{
130             if(fabs(y)<=eps&&fabs(x)<=eps){
131                 printf("Yes\n");
132                 continue;
133             }
134             if(fabs(y)<eps){
135                 bool ck=queryx(root,(x>0?1:-1),(x*x)/x/2.);
136                 if(ck&&use) puts("Yes"); else puts("No");
137                 continue;
138             }
139             bool ck; double k,b;
140             b=(x*x+y*y)/(2*y); k=-x/y;
141             if(y<0) ck=queryl(root,k,b);
142             else ck=queryr(root,k,b);
143             if(ck&&use) puts("Yes"); else puts("No");
144         }
145     }
146 }

 

posted @ 2017-12-07 10:32  AlphaInf  阅读(488)  评论(5编辑  收藏  举报