• bzoj4642: 泡泡


    Description

    "OI真的像是一条奇趣横生的路啊,也许它是绕过了高考的大山,也许确实有通往大学的捷径。但我,真的,真的只在
    乎那路上美丽的泡泡。"
    --TB
     
    TB喜欢所有自然的事物。比如说松爷的仙人掌,Picks的多项式导论,当然,还有OI路上美丽的泡泡。这些泡泡可
    以视作某一平面上的一些圆。由于泡泡的特殊性质,当两个泡泡在这一平面上相切的时候,TB认为这对泡泡是自然
    的,然而如果它们相交或者包含的话,泡泡就会破裂而无法继续存在(即不会存在相交或包含的情况)。TB想知道
    有多少对泡泡是自然的。

    Input

    输入文件的第一行包含一个正整数n,表示泡泡的个数。
    接下来n行,每行三个整数x,y,r,表示一个泡泡的圆心和半径。
    对于所有数据,|x|,|y|,r<=10^9, n<=500000
    数据保证所有的泡泡都是存在的,既不会出现相交或者包含的关系。

    Output

    一行,表示有多少对自然的泡泡。
    首先旋转坐标系避免一些特判

    用扫描线处理,由于圆互不包含/相切,扫描线上用平衡树维护线上圆的y坐标

    当线上新增加一个圆时,检查y坐标在其上/下的圆是否与其相切

    当线上删除一个圆时,检查y坐标在其上、下的两圆是否相切

    以上两个判定可能重复,最后要去重

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    typedef long double ld;
    const ld _0=1e-8,_s=std::sin(0.43415),_c=std::cos(0.43415);
    int ans=0;
    struct cir{
        ld x,y,r;
    }cs[500010];
    struct event{
        ld x;
        int id,type;
    }es[1000010];
    std::pair<int,int>as[1500050];
    int ap=0;
    bool operator<(event a,event b){
        return a.x<b.x;
    }
    struct cmp{bool operator()(int x,int y){return cs[x].y<cs[y].y;}};
    std::set<int,cmp>line;
    void chk(int a,int b){
        ld x=cs[a].x-cs[b].x,y=cs[a].y-cs[b].y;
        if(std::fabs(std::sqrt(x*x+y*y)-cs[a].r-cs[b].r)<_0){
            if(a>b){int c=a;a=b;b=c;}
            as[ap++]=std::make_pair(a,b);
        }
    }
    int main(){
        int n=_int();
        for(int i=0;i<n;i++){
            int x,y,r;
            scanf("%d%d%d",&x,&y,&r);
            cs[i].x=_c*x+_s*y;
            cs[i].y=-_s*x+_c*y;
            cs[i].r=r;
            es[i<<1]=(event){cs[i].x-cs[i].r,i,1};
            es[i<<1^1]=(event){cs[i].x+cs[i].r,i,0};
        }
        n<<=1;
        std::sort(es,es+n);
        for(int i=0;i<n;i++){
            event w=es[i];
            if(w.type){
                std::set<int,cmp>::iterator it=line.upper_bound(w.id);
                if(it!=line.end())chk(*it,w.id);
                if(it!=line.begin())--it,chk(*it,w.id);
                line.insert(w.id);
            }else{
                std::set<int,cmp>::iterator it=line.find(w.id);
                if(it!=line.begin()){
                    int a=*--it;++it;++it;
                    if(it!=line.end())chk(*it,a);
                    --it;
                }
                line.erase(it);
            }
        }
        std::sort(as,as+ap);
        if(ap)ans=1;
        for(int i=1;i<ap;i++)if(as[i]!=as[i-1])++ans;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Agile PLM bom表结构学习笔记
    火狐书签同步服务无法同步问题解决
    EasyExcel使用笔记
    给EasyUI查询按钮添加回车事件.
    让bat异常之后不直接关闭窗口的办法.
    DROP TABLE、TRUNCATE TABLE和DELETE的区别
    DUMPBIN工具的使用
    Java Build Path 详解
    用eclipse中打开已存在的Java Project
    .net core、微服务 开源项目
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5677347.html
Copyright © 2020-2023  润新知