zoukankan      html  css  js  c++  java
  • POJ 2932 Coneology计算最外层圆个数

     平面上有n个两两没有公共点的圆,i号圆的圆心在(xi,yi),半径为ri,编号从1开始。求所有最外层的,即不包含于其他圆内部的圆。输出符合要求的圆的个数和编号。n<=40000. 

    (注意此题无相交相切!!!)
    工具:扫描线+set 

    中心思想:
    边界分左右端点,如图,当扫描线与k号圆左端点相切,之前用set维护一个y纵坐标的二叉树,那我们在二叉树中查找离k号圆纵坐标最近的上下两个圆(A,B),让k与A,B判是否内含即可,为什么是AB?假设有C点(离k远一些)包含k,但A不包含k,那么一定有A,C相交,这不符合题意。
    之后,当扫到右端点,从set中删掉这个圆(即图中的D,因为它对后面k的判断没卵关系,而且还可能阻碍A,B)

    上代码:

    typedef pair<double,int>P;
    
    struct node{
    double x,y,r;
    }nod;
    
    bool inside(int a,b){//判断a是否在b中,半径大于圆心距
    double dx=node[a].x-node[b].x,dy=node[a].y-node[b].y;
    return dx*dx+dy*dy-node[b].r*node[b].r<=eps;
    }
    
    void solve(){
    vector<P>point;
    set<P>outer;//记录与当前扫描线相交的最外层圆集合
    vector<int>ans;//真正存储最外层圆集合
    For(i,1,n){
    point.pb(P(nod[i].x-nod[i].r,i));//记录左端点
    point.pb(P(nod[i].x+nod[i].r,i+n));//记录右端点
    }
    sort(point+1,point+1+n);
    For(i,0,point.size()-1){
    int id=point[i].sd;
    if(point[i].sd<n){//扫到左端点
    set<P>::iterator it=outer.lower_bound(P(nod[id].y,id));//二分找A,B
    if(it!=outer.begin()&&inside(id,it->sd))continue;
    if(it!=outer.end()&&inside(id,(--it)->sd))continue;
    ans.pb(P(nod[id].y,id));
    outer.insert(P(nod[id].y,id));
    }else outer.erase(P(node[id].y,id));   //扫到右端点,删掉
    }
    sort(ans.begin(),ans.end());
  • 相关阅读:
    第十二章 满城搜索 [转载]
    第十三章 平安是福
    第三十章 就是他!
    CyberArticle和Live Writer的比较
    NET CMS 大全
    第十五章 禹皇门,震动!
    第六篇 匹马行天下 第二十三章 血流成河,悟!
    第二十八章 震天怒吼
    今天终于找了一个代理登陆了传说中的三个网站
    第十六章 夜深人静
  • 原文地址:https://www.cnblogs.com/planche/p/9420516.html
Copyright © 2011-2022 走看看