2961: 共点圆

2961: 共点圆

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 875  Solved: 375
[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

思路来自:这里

推荐论文:许昊然 《浅谈数据结构题的几个非经典解法》

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#define pf(x) ((x)*(x))
#define IN inline
#define inf 1e20
using namespace std;
const int N=5e5+5;
const double eps=1e-10;
struct node{
    int opt,p,id;
    double x,y,k;
    bool operator <(const node &t)const{
        return k<t.k;
    }
}a[N],b[N];
int n,cnt,q[N];
bool ok[N];char s1[30],s2[30],s3[30];
double getk(int x,int y){
    if(fabs(a[x].x-a[y].x)<eps) return inf;
    return (a[x].y-a[y].y)/(a[x].x-a[y].x);
}
double dis(int x,int y){
    return pf(a[x].x-a[y].x)+pf(a[x].y-a[y].y);
}
//不知道为什么4360 ms巨慢(有人跑788 ms)太弱了! 
void CDQ(int l,int r){
    if(l==r) return ;
    int mid=l+r>>1,i=1,k=mid+1,j=l,tp=0;
    for(i=l;i<=r;i++){
        if(a[i].id<=mid)
            b[j++]=a[i];
        else
            b[k++]=a[i];
    }
    for(i=l;i<=r;i++) a[i]=b[i];
    CDQ(l,mid);//本题只需要维护上凸包,下凸包是x轴 
    for(i=l;i<=mid;i++) if(!a[i].opt){
        for(;tp>1&&getk(q[tp-1],i)<getk(q[tp-1],q[tp])+eps;tp--);
        q[++tp]=i;
    }
    for(j=1,i=mid+1;i<=r;i++) if(a[i].opt){
        for(;j<tp&&getk(q[j],q[j+1])<a[i].k;j++);
        if(j<=tp&&dis(q[j],0)<dis(q[j],i)) ok[a[i].p]=0;
    }
    CDQ(mid+1,r);
    for(i=j=l,k=mid+1;i<=r;i++){
        if((j<=mid&&a[j].x<a[k].x)||k>r)
            b[i]=a[j++];
        else
            b[i]=a[k++];
    }
    for(i=l;i<=r;i++) a[i]=b[i];
}
int main(){
    scanf("%s",s1);n=atoi(s1);
    bool flag=0;
    for(int i=1;i<=n;i++){
        scanf("%s%s%s",s1,s2,s3);
        a[i].opt=s1[0]-'0';a[i].x=atof(s2);a[i].y=atof(s3);
        if(a[i].opt) a[i].p=++cnt,ok[cnt]=flag;else flag=1;
        a[i].k=-a[i].x/a[i].y;a[i].id=i;
    }
    sort(a+1,a+n+1);CDQ(1,n);
    for(int i=1;i<=cnt;i++) puts(ok[i]?"Yes":"No");
    return 0;
}

 

posted @ 2017-01-24 20:30  神犇(shenben)  阅读(463)  评论(0编辑  收藏  举报