bzoj2961&&bzoj4140 共点圆

题目描述

  在平面直角坐标系中,Wayne需要你完成n次操作,操作只有两种:
  1.0 x y。表示在坐标系中加入一个以(x, y)为圆心且过原点的圆。
  2.1 x y。表示询问点(x, y)是否在所有已加入的圆的内部(含圆周),且至少在一个圆内部(含圆周)。
  为了减少你的工作量,题目保证圆心严格在x轴上方(纵坐标为正),且横坐标非零。


输入格式

  第1行一个整数n。
  接下来n行,每行第一个数是0或1,分别表示两种操作。
  接着有两个实数x和y,具体意义见题面。


输出格式

  对于每个询问操作,如果点在所有已加入的圆内(或圆周上),则输出“Yes”(不含引号);否则输出“No”(不含引号)。

 


数据范围

       对于100%的数据,n≤500000,所有坐标绝对值不超过10000。 


 

  • 题解

    • 在一个圆内$(x-a)^2 + (y-b)^2 <=  x^2 + y^2$,化简得$ax + by >= \frac{a^2 + b^2}{2}$,
    • 右边是定值,求出$ax+by$的最小值即可判断,做法类似bzoj3533
    • 如果对时间分治,每次对区间左边求凸包,$n \ logn$可以实现;
    • bzoj4140要求强制在线,可以采用二进制分组
    • 由于只会从后面查询,类似树状数组,每次重构末尾的$lowbit$位的凸包,查询不断-=lowbit(i)三分;
    • 注意复杂度的理解:
    • 考虑$n$位二进制数$N$,$lowbit$为第$i$位的有,$2^{n-i}$个,
    • $\sum_{i=0}^{n-1} 2^i  \ * \  2^{n-i} = N \ log_{2} \ N$
 1 #include<bits/stdc++.h>
 2 #define ld double
 3 #define il inline
 4 using namespace std;
 5 const int N=500010;
 6 const ld eps=1e-9;
 7 int n,m,st1[N],ed1[N],st2[N],ed2[N],top,cnt;
 8 ld mn;
 9 il int dcmp(ld x){return fabs(x)<eps?0:x<0?-1:1;}
10 struct P{
11     ld x,y;
12     P(ld X=0,ld Y=0):x(X),y(Y){};
13     bool operator <(const P&a)const{return fabs(x-a.x)<eps?y<a.y:x<a.x;}
14     P operator -(const P&a)const{return P(x-a.x,y-a.y);}
15 }q[N],p[N],t[N],Q; 
16 ld crs(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
17 ld dot(const P&a,const P&b){return a.x*b.x+a.y*b.y;}
18 void ask(int l,int r){
19     while(r-l>=3){
20         int mid=(r-l)/3,mid1=l+mid,mid2=r-mid;
21         if(dot(q[mid1],Q)>dot(q[mid2],Q))l=mid1;
22         else r=mid2;
23     }
24     for(int i=l;i<=r;++i)mn=min(mn,dot(q[i],Q));
25 }
26 int main(){
27     #ifndef ONLINE_JUDGE 
28     freopen("bzoj2961.in","r",stdin);
29     freopen("bzoj2961.out","w",stdout);
30     #endif
31     scanf("%d",&n);
32     for(int i=1,op;i<=n;++i){
33         scanf("%d",&op);
34         if(op==0){
35             m++;scanf("%lf%lf",&p[m].x,&p[m].y);
36             p[m].x+=cnt,p[m].y+=cnt;
37             int l=m-(m&-m)+1,r=m;
38             st1[m]=top=l;
39             for(int j=l;j<=r;++j)t[j]=p[j];
40             sort(t+l,t+r+1);
41             q[top]=t[l];
42             for(int j=l+1;j<=r;++j){
43                 while(top>l&&dcmp(crs(q[top]-q[top-1],t[j]-q[top]))<=0)top--;
44                 q[++top]=t[j];
45             }
46             int now=ed1[m]=st2[m]=top;
47             for(int j=r-1;j>=l;--j){
48                 while(top>now&&dcmp(crs(q[top]-q[top-1],t[j]-q[top]))<=0)top--;
49                 if(j>l)q[++top]=t[j];
50             }
51             ed2[m]=top;
52         }else{
53             scanf("%lf%lf",&Q.x,&Q.y);
54             Q.x+=cnt,Q.y+=cnt;
55             if(!m){puts("No");continue;}
56             mn = 1e18;
57             for(int j=m;j;j-=j&-j){
58                 if(Q.y>0)ask(st1[j],ed1[j]);
59                 else ask(st2[j],ed2[j]),mn=min(mn,dot(Q,q[st1[j]]));
60             }
61             if(dcmp(mn*2-Q.x*Q.x-Q.y*Q.y)>=0)puts("Yes"),cnt++;
62             else puts("No");
63         }
64     }
65 }
bzoj2961&&4140

 

posted @ 2019-01-17 07:54  大米饼  阅读(202)  评论(0编辑  收藏  举报