• 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());
  • 相关阅读:
    在数据库里进行分页处理
    new Date()在IE,谷歌,火狐上的一些注意项
    sql的一些小东西
    将sql数据库逆向生成PDM模型
    关于禁止在 .NET Framework 中执行用户代码。启用 "clr enabled" 配置选项
    MVC的Model层中的一些便签
    通过URL推送POST数据
    Python 关键字
    Python 标识符
    Python 注释(Python Comments)用法详解
  • 原文地址:https://www.cnblogs.com/planche/p/9420516.html
Copyright © 2020-2023  润新知