【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 }