[bzoj2961] 共点圆

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

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

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

Sample Input
5
0 2.0000 3.0000
0 4.0000 1.0000
1 1.000000 1.000000
0 -3.0000 2.0000
1 1.000000 1.000000

Sample Output
Yes
No

  n≤500000,所有坐标绝对值不超过10000。

  输入数据保证圆心纵坐标为正,横坐标非零。

  CDQ分治..这几天重新学了一下发现自己还是不怎么会..

  首先问题可以变成,每次给个半平面,询问是否所有圆心都在它里面。

  具体该在上凸包还是下凸包查就看推出来的式子了..

  主要是这题数据范围有点大,CDQ的时候不能多带log...

  要线性建区间[l,mid]里点的凸包的话,得使[l,mid]里的点x坐标有序;要线性查询[mid+1,r]里所有询问的话,得让[mid+1,r]里询问的斜率有序;而输入顺序本身又有一维。。

  所以最开始按照斜率排一下序,每次分治时按输入顺序分到左右两边,先处理[l,mid],然后再建凸包处理[mid+1,r]里的询问,最后把[l,r]按照x坐标归并排序一下...就都满足了..

  如果每次建凸包不是重新建,而是把两个小的合成一个大的,似乎就不用想那么多了?

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<cstdlib>
  7 #include<queue>
  8 #define ll long long
  9 #define ui unsigned int
 10 #define d double
 11 using namespace std;
 12 const int maxn=500023;const d eps=1e-7;
 13 struct zsq{bool ask;int id;d x,y,k;}q[maxn];
 14 struct zstb{int l,r;}stb[maxn],xtb[maxn];int tot;
 15 int st[maxn<<1],TOP,dl[maxn],tmpdl[maxn];
 16 int i,j,k,n,m;
 17 bool gg[maxn],ask[maxn];
 18
 19 int ra,fh;char rx;
 20 inline int read(){
 21     rx=getchar(),ra=0,fh=1;
 22     while(rx!=‘-‘&&(rx<‘0‘||rx>‘9‘))rx=getchar();
 23     if(rx==‘-‘)fh=-1,rx=getchar();
 24     while(rx>=‘0‘&&rx<=‘9‘)ra=ra*10+rx-48,rx=getchar();return ra*fh;
 25 }
 26
 27 inline d getk(int a,int b){return (q[b].y-q[a].y)/(q[b].x-q[a].x);}
 28 inline bool istb(int a,int b,int c,bool isstb){
 29     if(isstb)return (q[c].x-q[b].x)*(q[b].y-q[a].y) > (q[b].x-q[a].x)*(q[c].y-q[b].y);
 30     else return (q[b].x-q[a].x)*(q[c].y-q[b].y) > (q[c].x-q[b].x)*(q[b].y-q[a].y);
 31 }
 32
 33 inline bool check(int a,int b){//点b在圆a内
 34 //  printf("check:  %d  %d    %.2lf   %.2lf\n",a,b,q[a].x*q[a].x+q[a].y*q[a].y , (q[a].x-q[b].x)*(q[a].x-q[b].x)+(q[a].y-q[b].y)*(q[a].y-q[b].y));
 35     return q[a].x*q[a].x+q[a].y*q[a].y +eps > (q[a].x-q[b].x)*(q[a].x-q[b].x)+(q[a].y-q[b].y)*(q[a].y-q[b].y);
 36 }
 37 inline void buildtb(int x,int l,int r){
 38     int i;
 39 //  printf("buildtb:");for(i=l;i<=r;i++)if(!q[dl[i]].ask)printf("    (%.2lf,%.2lf)",q[dl[i]].x,q[dl[i]].y);puts("");
 40
 41     stb[x].l=TOP+1;
 42     for(i=l;i<=r;i++)if(!q[dl[i]].ask){
 43         while(TOP>stb[x].l&&!istb(st[TOP-1],st[TOP],dl[i],1))TOP--;
 44         if(TOP>=stb[x].l&&q[st[TOP]].x==q[dl[i]].x)
 45             if(q[dl[i]].y>q[st[TOP]].y)TOP--;else continue;
 46         st[++TOP]=dl[i];
 47     }stb[x].r=TOP;
 48
 49     xtb[x].l=TOP+1;
 50     for(i=l;i<=r;i++)if(!q[dl[i]].ask){
 51         while(TOP>xtb[x].l&&!istb(st[TOP-1],st[TOP],dl[i],0))TOP--;
 52         if(TOP>=xtb[x].l&&q[st[TOP]].x==q[dl[i]].x)
 53             if(q[dl[i]].y<q[st[TOP]].y)TOP--;else continue;
 54         st[++TOP]=dl[i];
 55     }xtb[x].r=TOP;
 56 }
 57 void solve(int l,int r){
 58     if(l==r)return;
 59     int i,x=++tot,mid=l+r>>1,r1=l,r2=mid+1;
 60
 61     for(i=l;i<=r;i++)if(q[dl[i]].id<=mid)tmpdl[r1++]=dl[i];else tmpdl[r2++]=dl[i];
 62     memcpy(dl+l,tmpdl+l,(r-l+1)<<2);solve(l,mid);
 63 //  printf("solve:%d--%d\n",l,r);
 64 //  for(i=l;i<=r;i++)printf("   %d",dl[i]);puts("");
 65
 66     TOP=0,buildtb(x,l,mid);int top1=stb[x].r,top2=xtb[x].l,now;
 67 //  printf("STB:  ");for(i=stb[x].l;i<=stb[x].r;i++)printf(" (%.2lf,%.2lf)",q[st[i]].x,q[st[i]].y);puts("");
 68 //  printf("XTB:  ");for(i=xtb[x].l;i<=xtb[x].r;i++)printf(" (%.2lf,%.2lf)",q[st[i]].x,q[st[i]].y);puts("");
 69     if(stb[x].l<=stb[x].r)
 70     for(i=mid+1;i<=r;i++)if(q[now=dl[i]].ask&&!gg[q[now].id]&&q[now].y!=0){
 71         if(q[now].y<0){
 72             while(top1>stb[x].l&&getk(st[top1-1],st[top1])<=q[now].k)top1--;
 73             if(!check(st[top1],now))gg[q[now].id]=1;
 74         }else{
 75             while(top2<xtb[x].r&&getk(st[top2],st[top2+1])<=q[now].k)top2++;
 76             if(!check(st[top2],now))gg[q[now].id]=1;
 77         }
 78     }
 79     solve(mid+1,r);
 80
 81     r1=l,r2=mid+1;
 82     for(i=l;i<=r;i++)tmpdl[i]=((q[dl[r1]].x<=q[dl[r2]].x&&r1<=mid)||r2>r)?dl[r1++]:dl[r2++];
 83     memcpy(dl+l,tmpdl+l,(r-l+1)<<2);
 84 }
 85
 86 bool operator <(zsq a,zsq b){return a.k<b.k;}
 87 int main(){
 88     n=read();d mxx=-1e9,mnx=1e9;
 89     for(i=1;i<=n;i++){
 90         q[i].ask=ask[i]=read(),gg[i]=!q[i].ask,
 91         scanf("%lf%lf",&q[i].x,&q[i].y);
 92         if(!q[i].y){
 93             if(q[i].x>0)gg[i]=mnx*2<eps+q[i].x;
 94             if(q[i].x<0)gg[i]=mxx*2>eps+q[i].x;
 95         }else q[i].k=-q[i].x/q[i].y;
 96         if(!q[i].ask)mxx=max(mxx,q[i].x),mnx=min(mnx,q[i].x);
 97         q[i].id=dl[i]=i;
 98     }
 99     sort(q+1,q+1+n);
100 //  for(i=1;i<=n;i++){
101 //      if(q[dl[i]].ask)printf("ask:");else printf("ins:");
102 //      printf("  %.2lf,%.2lf    k:%.2lf\n",q[i].x,q[i].y,q[i].k);
103 //  }
104     solve(1,n);
105 //  for(i=1;i<=n;i++)printf("   (%.2lf,%.2lf)",q[dl[i]].x,q[dl[i]].y);puts("");
106 //  TOP=0,++tot,buildtb(tot,1,n);for(i=xtb[tot].l;i<=xtb[tot].r;i++)printf(" (%.2lf,%.2lf)",q[st[i]].x,q[st[i]].y);puts("");
107     bool flag=0;
108     for(i=1;i<=n;i++)if(!ask[i])flag=1;else puts((flag&&!gg[i])?"Yes":"No");
109 }

时间: 2024-08-08 14:19:18

[bzoj2961] 共点圆的相关文章

【bzoj2961】 共点圆

http://www.lydsy.com/JudgeOnline/problem.php?id=2961 (题目链接) 题意 按照一定的顺序给出一些圆和一些点,对于每一个点问是否在所有圆内. Solution 我算是明白计算几何题是有多蛋疼了. 圆包含点$(x_0,y_0)$的条件:$$x*x+y*y>=(x-x_0)*(x-x_0)+(y-y_0)*(y-y_0)$$ $$-2x_0+x_0^2+y_0^2<=2y_0y$$ 题目只说圆心的纵坐标大于$0$,气的我吐出一口老血.所以根据$y_

BZOJ 2961 共点圆 CDQ分治+凸包

题目大意:给定平面,多次插入点和圆,每次插入点时询问当前插入的点是否在之前插入的所有圆中并且至少在一个圆中 直接用数据结构维护这些点和圆不是很好写,我们考虑CDQ分治 对于每层分治,我们需要对于[mid+1,r]中的每个点求出[l,mid]中是否所有的圆都覆盖了这个点 设点的坐标为(x0,y0),那么这个点在所有圆内必须满足对于所有的圆心(x,y),(x-x0)^2+(y-y0)^2<=x^2+y^2,即2*x*x0+2*y*y0>=x0^2+y0^2 我们发现上面的式子是一个半平面,斜率为-

总结与心得(持续更新)

不知道为什么,刚学的算法过了2个月就忘得一干二净,我并没有背代码啊,当时学的时候还刷了好多题来着→_→,我是不是大脑能力严重衰退了. 动态规划 单调队列 一般情况下,${dp}$方程可以搞成这样:${f_i=f_j+t_j+t_i}$,只要其中没有变量同时与${i,j}$都有关,那么我们可以用单调队列来做,单调队列里面元素的关键字就是与${j}$有关的东西${f_j+t_j}$.example:生产产品 有些比较特殊的,虽然存在同时与${i,j}$相关的函数,但是这个函数比较简单,使得已经存在在

分治笔记

分治 一.简单介绍 二.集中题目 1.  动态最小生成树(了解) 2.  CDQ分治 (1)       蝗虫(运用) (2)       CASH(了解) (3)       共点圆(了解) 3.  树分治 (1)       树链剖分(运用)  例题::BZOJ2243 每个点记录siz.son.fa.top.dfn (siz:该点子树大小.son:该点重链上的儿子(就是重儿子),top:该点重链的顶端,如果不在重链上则top=本身) 先dfs一遍,求出siz,son,fa 再dfs一遍(依

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

Spring mvc 中使用ftl引用共通文件出错 FreeMarker template error: Error reading included file &quot;/WEB-INF/ftl/common/errormessage.ftl&quot;

初次接触spring mvc,想做一个小的练习项目,结果在ftl文件中引用其它的共通ftl文件时出错. 目录结构如图所示,想在login.ftl中引用common下的errormessage.ftl <#include '/WEB-INF/ftl/common/errormessage.ftl' /> 结果画面报错: FreeMarker template error: Error reading included file "/WEB-INF/ftl/common/errormes

一球从M米高度自由下落,每次落地后返回原高度的一半,再落下。 它在第N次落地时反弹多高?共经过多少米? 保留两位小数

题目描述 输入 M N 输出 它在第N次落地时反弹多高?共经过多少米? 保留两位小数,空格隔开,放在一行 样例输入 1000 5 样例输出 31.25 2875.00 代码:#include<stdio.h>int main(){    double M,sum=0;    int N,i;    scanf("%lf%d",&M,&N);    sum=M;    for(i=2;i<=N;i++)    {                 M=M/

材料管理框架:一个共通的viewModel搞定所有的分页查询

前言 大家看标题就明白了我想写什么了,在做企业信息化系统中可能大家写的最多的一种页面就是查询页面了.其实每个查询页面,除了条件不太一样,数据不太一样,其它的其实都差不多.所以我就想提取一些共通的东西出来,再写查询时只要引入我共通的东西,再加上极少的代码就能完成.我个人比较崇尚代码简洁干净,有不合理的地方欢迎大家指出. 这篇文章主要介绍两个重点:1.前台viewModel的实现.2.后台服务端如何简洁的处理查询请求. 需求分析 查询页面要有哪些功能呢 1.有条件部输入查询条件(这个不打算做成共通的

资本与互联网共舞下的体育产业如何向前发展?

7月11日,2016年欧洲杯以葡萄牙1—0战胜法国夺冠落下帷幕.而在这期间,中国的球迷也是在熬夜看球,也许还沉浸在欧洲杯的激动心情中.根据欧足联公布的数据显示,欧洲杯开赛的5天内,在中国大陆的央视直播欧洲杯赛,其平均收视率就达到1.49%,也就意味着有3500多万精准人群在固定收看比赛.除了电视媒体这一块,还有新媒体下的视频直播平台.脱口秀等网络节目对欧洲杯推出多元化节目也获得很高的点击量.而足球的热潮还没有褪去,我们就要在八月迎来奥运会,这一重大的体育赛事又将为中国的年轻体育迷们带来一场场激动