• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
AC_Artist.zig_zag
然而我依然在补题、
博客园    首页    新随笔    联系   管理    订阅  订阅

bzoj2961 共点圆——陈丹琪分治

最近惊讶地发现陈丹琪分治又名时间分治......

写完cash以后,突然就觉得分治法解决一些需要高级数据结构维护的题目非常地爽,于是我就很2b地去做共点圆了。对于一个几乎没有做过计算几何的我,居然还傻傻地以为直接用斜率就可以搞了......并且一开始解不等式居然忘变号了,以为只用维护一个下半凸壳就行了......

以上都是废话。

这个题给过圆心的点,询问点是不是在所有圆内,运用时间分治,我们变成了用[l,mid]段的圆去计算[mid+1,r]段的点,以更新答案。因为这个题中添加操作之间对答案的贡献是互不影响的,这样我们通过分治创造了一种序,就是先给出圆,后计算点。于是这个问题就比价容易了,符合条件的圆心(x,y),一定在2*xo*x+2*yo*y>=xo2+yo2这个半平面内,于是我们对[l,mid]的圆心做一个全凸包,然后二分查找斜率-xo/yo卡到的点,然后判断这个点是不是符合条件就行了。

详细请见2013xhr论文

circle
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 #define maxn 600000
  7 #define inf 1e12
  8 #define eps 1e-9
  9 using namespace std;
 10 struct query
 11 {
 12     int tp;
 13     double x,y;
 14 }q[maxn],p[maxn],up[maxn],dw[maxn];
 15 int ans[maxn];
 16 int n,tot,t1,t2;
 17 double fabs(double x)
 18 {
 19     return (x>0)?x:-x;
 20 }
 21 query operator -(const query &a,const query &b)
 22 {
 23     query tmp;
 24     tmp.x=a.x-b.x; tmp.y=a.y-b.y;
 25     return tmp;
 26 }
 27 double operator *(const query &a,const query &b)
 28 {
 29     return a.x*b.y-a.y*b.x;
 30 }
 31 double operator ^(const query &a,const query&b)
 32 {
 33     return a.x*b.x+a.y*b.y;
 34 }
 35 bool operator <(const query &a,const query &b)
 36 {
 37     return (fabs(a.x-b.x)<eps)?a.y<b.y:a.x<b.x;
 38 }
 39 
 40 void ask(int i)
 41 {
 42     query tmp;
 43     if (q[i].y<0)
 44     {
 45         int l=1,r=t1;
 46         while (l<=r)
 47         {
 48             int mid=(l+r)>>1;
 49             if ((q[i]^(up[mid+1]-up[mid]))>-eps) r=mid-1,tmp=up[mid];
 50             else l=mid+1;
 51         }
 52     }
 53     else
 54     {
 55         int l=1,r=t2;
 56         while (l<=r)
 57         {
 58             int mid=(l+r)>>1;
 59             if ((q[i]^(dw[mid]-dw[mid+1]))<eps) r=mid-1,tmp=dw[mid];
 60             else l=mid+1;
 61         }
 62     }
 63     if (2*q[i].x*tmp.x+2*q[i].y*tmp.y-(q[i].x*q[i].x+q[i].y*q[i].y)<eps) ans[i]=0;
 64 }
 65 
 66 void solve(int l,int r)
 67 {
 68     if (l==r) return ;
 69     int mid=(l+r)>>1;
 70     solve(l,mid);
 71     solve(mid+1,r);
 72     tot=0;
 73     for (int i=l;i<=mid;i++)
 74         if (q[i].tp==0) p[++tot]=q[i];
 75     sort(p+1,p+tot+1);
 76     t1=t2=0;
 77     for (int i=1;i<=tot;i++)
 78     {
 79         while (t1>=2&&(up[t1]-up[t1-1])*(p[i]-up[t1])>-eps) t1--;
 80         up[++t1]=p[i];
 81     }
 82     for (int i=tot;i>=1;i--)
 83     {
 84         while (t2>=2&&(dw[t2]-dw[t2-1])*(p[i]-dw[t2])>-eps) t2--;
 85         dw[++t2]=p[i];
 86     }
 87     up[t1+1].x=up[t1].x+eps; up[t1+1].y=-inf;
 88     dw[t2+1].x=dw[t2].x-eps; dw[t2+1].y=inf;
 89     for (int i=mid+1;i<=r;i++)
 90         if (q[i].tp==1) if (ans[i]) ask(i);
 91 }
 92 
 93 int main()
 94 {
 95     //freopen("circle.in","r",stdin);
 96     //freopen("circle.out","w",stdout);
 97     scanf("%d",&n);
 98     int now=0;
 99     for (int i=1;i<=n;i++)
100     {
101         scanf("%d%lf%lf",&q[i].tp,&q[i].x,&q[i].y);
102         if (q[i].tp==0) now=1;
103         else ans[i]=now;
104     }
105     solve(1,n);
106     for (int i=1;i<=n;i++)
107         if (q[i].tp==1)
108             if (ans[i]==1)
109                 printf("Yes\n");
110             else 
111                 printf("No\n");
112     return 0;
113 }

 

AC without art, no better than WA !
posted @ 2013-04-25 21:11  Zig_zag  阅读(1563)  评论(1)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3