这题……一看圆不相交,直观上可以扫描线,每次插入和删除的时候判一下相邻的是否相切,然后……大概证一下,好像可以扫描线,然后写一发A了,发现确实可以扫描线……
注意写扫描线的比较函数的时候考虑各种相等情况
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 500010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
struct cir{
double x;
double y;
double r;
};
struct evt{
double x;
int bel;
int c;
friend bool operator <(evt x,evt y){
return fabs(x.x-y.x)>eps?x.x<y.x:x.c<y.c;
}
};
cir c[MAXN];
struct pt{
int bel;
int cl;
pt(){
}
pt(int _bel,int _cl){
bel=_bel;
cl=_cl;
}
double y();
friend bool operator <(pt x,pt y){
return x.bel==y.bel?x.cl<y.cl:fabs(x.y()-y.y())>eps?x.y()<y.y():c[x.bel].y!=c[y.bel].y?c[x.bel].y<c[y.bel].y:x.bel<y.bel;
}
};
int X;
evt e[MAXN*2];
set<pt>wzh;
int n,tot;
map<int,bool>nt[MAXN];
double pt::y(){
if(cl){
return ::c[bel].y+sqrt(::c[bel].r*::c[bel].r-(X-::c[bel].x)*(X-::c[bel].x));
}else{
return ::c[bel].y-sqrt(::c[bel].r*::c[bel].r-(X-::c[bel].x)*(X-::c[bel].x));
}
}
int main(){
int i;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);
}
for(i=1;i<=n;i++){
e[++tot].x=c[i].x-c[i].r;
e[tot].bel=i;
e[tot].c=0;
e[++tot].x=c[i].x+c[i].r;
e[tot].bel=i;
e[tot].c=1;
}
sort(e+1,e+tot+1);
for(i=1;i<=tot;i++){
X=e[i].x;
if(e[i].c==0){
set<pt>::iterator p=wzh.insert(pt(e[i].bel,0)).first;
if(p!=wzh.begin()){
p--;
pt x=*p;
p++;
pt y=pt(e[i].bel,0);
if(fabs((c[x.bel].x-c[y.bel].x)*(c[x.bel].x-c[y.bel].x)+(c[x.bel].y-c[y.bel].y)*(c[x.bel].y-c[y.bel].y)-(c[x.bel].r+c[y.bel].r)*(c[x.bel].r+c[y.bel].r))<eps){
nt[x.bel][y.bel]=1;
nt[y.bel][x.bel]=1;
}
}
if(p!=(--wzh.end())){
pt x=*(++p);
pt y=pt(e[i].bel,0);
if(fabs((c[x.bel].x-c[y.bel].x)*(c[x.bel].x-c[y.bel].x)+(c[x.bel].y-c[y.bel].y)*(c[x.bel].y-c[y.bel].y)-(c[x.bel].r+c[y.bel].r)*(c[x.bel].r+c[y.bel].r))<eps){
nt[x.bel][y.bel]=1;
nt[y.bel][x.bel]=1;
}
}
wzh.insert(pt(e[i].bel,1));
}
if(e[i].c==1){
wzh.erase(pt(e[i].bel,1));
set<pt>::iterator p=wzh.find(pt(e[i].bel,0));
if(p!=wzh.begin()&&(p!=--wzh.end())){
pt x=*(--p);
p++;
pt y=*(++p);
if(fabs((c[x.bel].x-c[y.bel].x)*(c[x.bel].x-c[y.bel].x)+(c[x.bel].y-c[y.bel].y)*(c[x.bel].y-c[y.bel].y)-(c[x.bel].r+c[y.bel].r)*(c[x.bel].r+c[y.bel].r))<eps){
nt[x.bel][y.bel]=1;
nt[y.bel][x.bel]=1;
}
}
wzh.erase(pt(e[i].bel,0));
}
}
int ans=0;
for(i=1;i<=n;i++){
ans+=nt[i].size();
}
printf("%d\n",ans/2);
return 0;
}
/*
7
0 0 1
2 0 1
4 0 1
6 0 1
0 2 1
0 4 1
0 6 1
*/