• BZOJ4140 : 共点圆加强版


    假设当前询问点为$(A,B)$,那么它在一个以$(x,y)$为圆心的圆里需要满足:

    $(x-A)^2+(y-B)^2leq x^2+y^2$

    $2Ax+2Bygeq A^2+B^2$

    等价于询问所有圆心与$(2A,2B)$的点积的最小值是否小于$A^2+B^2$。

    考虑将修改操作二进制分组,分成$O(log n)$段连续的修改区间,每一段建立上下凸壳维护,查询时在凸壳上三分。

    时间复杂度$O(nlog^2n)$,常数很小。

    #include<cstdio>
    #include<algorithm>
    #define N 500010
    int n,m,op,t,q[30],r1[30],r2[30],flag;double A,B,C,D;
    struct P{double x,y;}a[N],b[N],q1[N],q2[N];
    inline bool cmp1(const P&a,const P&b){return a.x==b.x?a.y>b.y:a.x<b.x;}
    inline bool cmp2(const P&a,const P&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
    inline void update(){
      while(t&&m-q[t]==q[t]-q[t-1])t--;q[++t]=m;
      int i,cnt=0,L=q[t-1]+1,R;
      for(i=L;i<=m;i++)b[cnt++]=a[i];
      std::sort(b,b+cnt,cmp1);
      for(q1[R=L]=b[0],i=1;i<cnt;q1[++R]=b[i++])while(R>L&&(q1[R].y-q1[R-1].y)*(b[i].x-q1[R].x)<=(b[i].y-q1[R].y)*(q1[R].x-q1[R-1].x))R--;
      r1[t]=R;
      std::sort(b,b+cnt,cmp2);
      for(q2[R=L]=b[0],i=1;i<cnt;q2[++R]=b[i++])while(R>L&&(q2[R].y-q2[R-1].y)*(b[i].x-q2[R].x)>=(b[i].y-q2[R].y)*(q2[R].x-q2[R-1].x))R--;
      r2[t]=R;
    }
    inline double mul(const P&b){return A*b.x+B*b.y;}
    inline void ask1(int l,int r){
      int m1,m2;double s1,s2;
      while(l<=r){
        int len=(r-l)/3;
        if((s1=mul(q1[m1=l+len]))<(s2=mul(q1[m2=r-len]))){
          if(s1<C){flag=1;return;}
          r=m2-1;
        }else{
          if(s2<C){flag=1;return;}
          l=m1+1;
        }
      }
    }
    inline void ask2(int l,int r){
      int m1,m2;double s1,s2;
      while(l<=r){
        int len=(r-l)/3;
        if((s1=mul(q2[m1=l+len]))<(s2=mul(q2[m2=r-len]))){
          if(s1<C){flag=1;return;}
          r=m2-1;
        }else{
          if(s2<C){flag=1;return;}
          l=m1+1;
        }
      }
    }
    inline void ask(){
      flag=0;
      for(int i=1;i<=t;i++){
        if(B<0)ask1(q[i-1]+1,r1[i]);else ask2(q[i-1]+1,r2[i]);
        if(flag)return;
      }
    }
    int main(){
      scanf("%d",&n);
      while(n--){
        scanf("%d%lf%lf",&op,&A,&B);A+=D,B+=D;
        if(!op)a[++m].x=A,a[m].y=B,update();
        else{
          if(!m){puts("No");continue;}
          C=A*A+B*B,A+=A,B+=B,ask();
          if(flag)puts("No");else puts("Yes"),D++;
        }
      }
      return 0;
    }
    

      

  • 相关阅读:
    深入理解javascript的this关键字
    很简单的JQuery网页换肤
    有关垂直居中
    层的半透明实现方案
    常用meta整理
    web前端页面性能优化小结
    关于rem布局以及sprit雪碧图的移动端自适应
    mysql入过的坑
    日期格式化函数
    基于iframe父子页面传值的方法。
  • 原文地址:https://www.cnblogs.com/clrs97/p/5008300.html
Copyright © 2020-2023  润新知