zoukankan      html  css  js  c++  java
  • 【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
    ");
    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 }
  • 相关阅读:
    mysql命令集锦
    linux 删除文件名带括号的文件
    linux下的cron定时任务
    struts2文件下载的实现
    贴一贴自己写的文件监控代码python
    Service Unavailable on IIS6 Win2003 x64
    'style.cssText' is null or not an object
    "the current fsmo could not be contacted" when change rid role
    远程激活程序
    新浪图片病毒
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7997879.html
Copyright © 2011-2022 走看看