【BZOJ2961】【Codevs2003】共点圆

来源:互联网 发布:反网络尖兵 编辑:程序博客网 时间:2024/05/24 15:37

2961: 共点圆
Time Limit: 30 Sec Memory Limit: 256 MB
Submit: 333 Solved: 141
[Submit][Status][Discuss]
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
HINT

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

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

  圆心坐标保留4位小数,询问点坐标保留6位小数,请选手注意控制精度。

Source

中国国家队清华集训 2012-2013 第二天

麻麻我终于会写半平面交了QUQ本来想练cdq玩的顺便学会了半平面交
虽然我的代码跑的奇慢荣登BZOJ倒数rank5但是毕竟A了不是吗233
这么简单的东西也不打太多注释了会被鄙视的(/ω\)
就是普通的凸包啊。。。
把插入的圆变成凸包点当半平面看凸包是否全部点在半平面内
具体做法2013集训队论文XHR神犇讲的很清楚了0-0我也不多说什么了(/ω\)

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 500100#define MAXDBL 1e20#define eps 1e-9using namespace std;int n;bool ans[MAXN];int flag;struct Query{    int t;    int op;    double x,y;    double k;    bool operator <(const Query& a)const{        return x<a.x;    }}q[MAXN],newq[MAXN];int num;bool com(Query a,Query b){    return a.t<b.t;}double slope(int a,int b){    if (!b) return -MAXDBL;    if (fabs(q[a].x-q[b].x)<eps) return MAXDBL;    return (q[b].y-q[a].y)/(q[b].x-q[a].x);}double dis(int a,int b){    return sqrt((q[a].x-q[b].x)*(q[a].x-q[b].x)+(q[a].y-q[b].y)*(q[a].y-q[b].y));}int stack1[MAXN],stack2[MAXN];//分别维护上凸线(stack1)和下凸线(stack2)bool comp(Query a,Query b){    return a.k<b.k;}void solve(int l,int r){    int mid=(l+r)>>1,tp1=l,tp2=mid+1;    if (l==r) return;    for (int i=l;i<=r;i++)        if (q[i].t<=mid) newq[tp1++]=q[i];        else newq[tp2++]=q[i];    memcpy(q+l,newq+l,sizeof(Query)*(r-l+1));    solve(l,mid);    int top1=0,top2=0,j=1;    for (int i=l;i<=mid;i++)    {        if (q[i].op==1) continue;        while (top1>1&&(slope(stack1[top1-1],stack1[top1])-slope(stack1[top1-1],i))<eps) stack1[top1--]=0;        stack1[++top1]=i;        while (top2>1&&(slope(stack2[top2-1],stack2[top2])-slope(stack2[top2-1],i))>eps) stack2[top2--]=0;        stack2[++top2]=i;    }    for (int i=mid+1;i<=r;i++)    {        if (q[i].op==0) continue;        if (q[i].y>eps)        {            while (j<top2&&slope(stack2[j],stack2[j+1])<q[i].k) stack2[j++]=0;            if (j<=top2&&dis(stack2[j],0)<dis(stack2[j],i)) ans[q[i].t]=1;        }        else        {            while (top1>1&&slope(stack1[top1-1],stack1[top1])<q[i].k) stack1[top1--]=0;            if(stack2[j]) printf("%lf %lf\n",q[stack2[j]].x,q[stack2[j]].y);            if (top1>=1&&dis(stack2[j],0)<dis(stack2[j],i)) ans[q[i].t]=1;        }    }    solve(mid+1,r);    tp1=l;tp2=mid+1;    for (int i=l;i<=r;i++)        if (tp1<=mid&&q[tp1]<q[tp2]||tp2>r) newq[i]=q[tp1++];        else newq[i]=q[tp2++];    memcpy(q+l,newq+l,sizeof(Query)*(r-l+1));}int main(){    scanf("%d",&n);    q[0].x=0;q[0].y=0;    for (int i=1;i<=n;i++) ans[i]=0;    for (int i=1;i<=n;i++)    {        scanf("%d%lf%lf",&q[i].op,&q[i].x,&q[i].y);        if (fabs(q[i].y)<=eps) q[i].k=MAXDBL;        else q[i].k=-q[i].x/q[i].y;        q[i].t=i;    }    sort(q+1,q+n+1,comp);    solve(1,n);    sort(q+1,q+n+1,com);    for (int i=1;i<=n;i++)        if (q[i].op==1)         {            if (!ans[q[i].t]&&flag) puts("Yes");            else puts("No");        }        else if (!flag) flag=1;}
1 0
原创粉丝点击