题意:给定n个不相交的圆,求哪些圆是最外层的(不包含与其他任何圆中)
用平面扫描的思想。
假设有三个圆a,b,c,若a包含b,b包含c,则a必包含c,所以检测一个圆如果被包含,只要检测他是否被最外面的那些圆包含即可。这样用一个set来维护最外面的那些圆的集合。
还有一个性质就是并不需要检测所有的最外层的圆,只需检测在set中y轴方向上距离最近的两个圆是否包含被检测的圆即可,这个画一下图就知道了。
所以流程就是先把所有圆的最左端,最右端排序,然后从左往右扫:
如果扫到左端的点,那么就判断一下当前set中y轴距离最近的两个圆是否包含它,如果不包含,那它也是最外层的点,也把他加到set里。并把这个圆加到答案中。
如果扫到右端的点,那么如果这个圆在set里就把它删掉。
因为判断inside时脑残的用了int型wa了一次。。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <algorithm>
#include <vector>
#define maxn 100010
using namespace std;
struct node{
int id;
double pos;
}N[100010];
double r[maxn],x[maxn],y[maxn];
set <pair<double ,int > >out;
vector <int >res;
bool cmp(node a,node b){
return a.pos<b.pos;
}
bool inside(int a,int b){
double tx=x[a]-x[b];
double ty=y[a]-y[b];
if(tx*tx+ty*ty<=r[b]*r[b])
return 1;
return 0;
}
int main(){
int n;
while(~scanf("%d",&n)){
out.clear();
res.clear();
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
N[i].pos=x[i]-r[i];
N[i].id=i;
N[i+n].pos=x[i]+r[i];
N[i+n].id=i+n;
}
sort(N+1,N+2*n+1,cmp);
for(int i=1;i<=2*n;i++){
int k=N[i].id;
if(k>n) k-=n;
if(N[i].id<=n){
set <pair<double,int > > ::iterator p;
p=out.lower_bound(make_pair(y[k],k));
if(p!=out.end()&&inside(k,p->second)) continue;
if(p!=out.begin()&&inside(k,(--p)->second)) continue;
out.insert(make_pair(y[k],k));
res.push_back(k);
}
else{
out.erase(make_pair(y[k],k));
}
}
sort(res.begin(),res.end());
printf("%d\n",res.size());
for(int i=0;i<res.size();i++){
printf("%d",res[i]);
if(i==res.size()-1) printf("\n");
else printf(" ");
}
}
return 0;
}