poj2932 Coneology【扫描线+set】

来源:互联网 发布:翻墙的软件 编辑:程序博客网 时间:2024/05/22 01:51

题目大意:

平面上N个两两没有公共点的圆,i号圆的半径为ri,圆心在(xi,yi),求所有在最外层,即不被包含在其他圆内部的圆 。

解题思路:

注意所给的圆都没有公共点。

维护一个set,里面保存着和扫描线相交的圆,再用扫描线从左往右扫。

如果扫到某圆的最左点,当它不被其他圆包含时,就把它加入到set中。

如果扫到是某圆的最右点,并且该圆在数据结构中,就把这个圆删掉。

怎么检查它有没有被其他圆包含呢?set里的圆(注意是不被其他圆覆盖的)互不相交,也就是说他们在当前的扫描线上占的区间也互不相交, 我们可以只记录圆心在扫描线的投影, 把低的投影称为前,把高的投影低称为后,那么可能覆盖当前圆的只可能是它的前一个圆或后一个圆。

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<ctime>#include<queue>#include<vector>#include<set>using namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());    if(c=='-')c=getchar(),f=-1;    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=40005;const double eps=1e-8;struct cone{    double r,x,y;    inline friend bool operator < (const cone &a,const cone &b)    {        if(a.x==b.x&&a.y==b.y)return a.r<b.r;        if(a.y==b.y)return a.x<b.x;        return a.y<b.y;    }}a[N];struct point{    double p;    int id,f;    inline friend bool operator < (const point &a,const point &b)    {        if(a.p==b.p)return a.f>b.f;        return a.p<b.p;    }}b[N<<1];int n,m,cnt;bool exist[N];set<cone>S;set<cone>::iterator it;bool in(cone u,cone v){    return (u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y)<=v.r*v.r;}int main(){    //freopen("lx.in","r",stdin);    //freopen("lx.out","w",stdout);    n=getint();    for(int i=1;i<=n;i++)    {        scanf("%lf%lf%lf",&a[i].r,&a[i].x,&a[i].y);        b[++m].p=a[i].x-a[i].r,b[m].id=i,b[m].f=1;        b[++m].p=a[i].x+a[i].r,b[m].id=i,b[m].f=0;    }    sort(b+1,b+m+1);    for(int i=1;i<=m;i++)    {        int x=b[i].id;        if(b[i].f==1)        {            S.insert(a[x]);            it=S.find(a[x]);            if(it!=S.begin())            {                cone t=*--it;++it;                if(in(a[x],t))                {                    S.erase(it);                    continue;                }            }            if(++it!=S.end())            {                cone t=*it;--it;                if(in(a[x],t))                {                    S.erase(it);                    continue;                }            }            exist[x]=true,cnt++;        }        else if(exist[x])         {            it=S.find(a[x]);            S.erase(it);        }    }    cout<<cnt<<'\n';    for(int i=1;i<=n;i++)        if(exist[i])cout<<i<<" ";    return 0;}