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 }
  • 相关阅读:
    在MFC中使用一个单独的类实现数据在各个类之间的传递
    在MFC中实现对象之间数据的传递。
    extern,头文件和ifndif宏
    在MFC下如何定义全局变量和全局函数
    语言当中一些经常看到 却又迷糊的修饰符
    C++基础之头文件和源文件的关系
    如何使用别人的代码 (特指在MFC里面 或者推广为C++里面)
    DataGird 相关
    在MFC里面使用ADO访问微软的ACCESS数据库 实现增删改查
    Invert Binary Tree
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7997879.html
Copyright © 2011-2022 走看看