POJ 2932 Coneology(扫描线)

【题目链接】 http://poj.org/problem?id=2932

【题目大意】

  给出N个两两没有公共点的圆,求所有不包含于其它圆内部的圆

【题解】

  我们计算出所有点在圆心所有y位置的x值,
  由于两两没有公共点,所以当我们对所有的x坐标进行扫描时,只要扫描相邻的x,
  判定扫描到的圆和与其x相邻的圆是否是圆包含关系就可以判断一个圆的位置
  扫描到左端点时,如果圆其被包含,则什么都不做,否则,将这个圆加入set中,
  当扫描到右端点时,如果圆被包含,则什么都不做,否则将圆从set中去除。

【代码】

#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
const int MAX_N=40010;
int N;
double x[MAX_N],y[MAX_N],r[MAX_N];
bool inside(int i,int j){
    double dx=x[i]-x[j],dy=y[i]-y[j];
    return dx*dx+dy*dy<=r[j]*r[j];
}
void solve(){
    vector<pair<double,int> >events;
    for(int i=0;i<N;i++){
        events.push_back(make_pair(x[i]-r[i],i));
        events.push_back(make_pair(x[i]+r[i],i+N));
    }
	  sort(events.begin(),events.end());
    set<pair<double,int> >outers;
    vector<int> res;
    for(int i=0;i<events.size();i++){
        int id=events[i].second%N;
        if(events[i].second<N){
            set<pair<double,int> >::iterator it=outers.lower_bound(make_pair(y[id],id));
            if(it!=outers.end()&&inside(id,it->second))continue;
            if(it!=outers.begin()&&inside(id,(--it)->second))continue;
            res.push_back(id);
            outers.insert(make_pair(y[id],id));
        }else outers.erase(make_pair(y[id],id));
    }sort(res.begin(),res.end());
    printf("%d\n",res.size());
    for(int i=0;i<res.size();i++){
        printf("%d%c",res[i]+1,i+1==res.size()?‘\n‘:‘ ‘);
    }
}
void init(){
    for(int i=0;i<N;i++)scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
}
int main(){
    while(~scanf("%d",&N)){
        init();
        solve();
    }return 0;
}

  

时间: 2024-12-30 04:17:40

POJ 2932 Coneology(扫描线)的相关文章

poj 2932 Coneology(扫描线+set)

Coneology Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3574   Accepted: 680 Description A student named Round Square loved to play with cones. He would arrange cones with different base radii arbitrarily on the floor and would admire

poj 2932 Coneology (扫描线)

题意 平面上有N个两两不相交的圆,求全部最外层的,即不被其它圆包括的圆的个数并输出 思路 挑战程序竞赛P259页 代码 /* ********************************************** Auther: xueaohui Created Time: 2015-7-25 16:56:13 File Name : poj2932.cpp *********************************************** */ #include <iostr

POJ 2932 Coneology (平面扫描)

Coneology Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3713   Accepted: 720 Description A student named Round Square loved to play with cones. He would arrange cones with different base radii arbitrarily on the floor and would admire

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相交,

poj 2932 Coneology 扫面线法

题意: 给n个无交点的圆,求这n个圆中不被其它圆包含的圆. 分析: 扫面线法,用二叉树(set+lowerbound方法)维护最外圆的集合. 代码: #include <iostream> #include <algorithm> #include <vector> #include <set> using namespace std; const int maxN=40012; double r[maxN],x[maxN],y[maxN]; int n;

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

POJ 1177 Picture(扫描线求周长)

与求面积并的差不多,但是这个与扫描的方向相同的情况不太好处理,如果扫描线离散化两次扫两遍其实也可以解决这个问题,但是这样无论在时间还是空间上稍微就有点浪费了啊.这里因为我是离散x坐标的所以对于平行于y轴的方向上的统计比较难统计.处理的方法是:标记区间左边的断点,和右边的断点,求出这个区间一共有多少个断点.就可以统计出平行于y轴的长度了.这里合并的时候需要判断右边的左区间和左边的右区间是否相同,如果相同的话,说明他们连接到了一起,要减去多加的. Picture Time Limit: 2000MS

poj 1177 Picture(扫描线+矩形周长并)

http://poj.org/problem?id=1177 求矩形的周长并,明确的一点是对于覆盖的边的长度忽略不计. 与求面积并类似,首先离散化,对矩形的每条横边从下往上扫描.扫描过程中要完成三个任务,更新相应的区间信息,求横边长,求竖边长. 节点信息: l,r:左右区间编号 cnt:表示该区间是否被完全覆盖.cnt > 0 表示完全覆盖,否则不完全覆盖. lp,rp:表示该区间的两个端点是否被覆盖,为1被覆盖,为0没被覆盖. num:该区间被覆盖的线段数目.例如区间[1,10],当更新[2,