Rt,思路就是扫描线+set维护圆的包含关系,实现就参考的第一篇题解,10pts。
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define Mp make_pair
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Rof(i,a,b) for(int i=a;i>=b;i--)
#define sqr(x) (x*x)
using namespace std;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
typedef pair<int,int> pii;
const int N=5e5+5;
const int mod=1e9+7;
const double eps=1e-9;
int read(){
int ans=0,flag=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')flag=-1;
for(;isdigit(ch);ch=getchar())ans=ans*10+(ch^48);
return ans*flag;
}
struct circle{
int x,y,r;
}c[N];
int n,lx,ans,d[N];
struct Node{
int type,id;
Node(int a=0,int b=0):type(a),id(b){}
double get(){return c[id].y+(double)type*(sqrt(sqr(c[id].r)-sqr(lx-c[id].x))+eps);} //求与扫描线的交点
friend bool operator<(Node a,Node b){return a.get()<b.get()-eps;}
};
struct line{
int type,x,id;
line(int a=0,int b=0,int c=0):type(a),x(b),id(c){}
friend bool operator<(const line &a,const line &b){return a.x<b.x;}
}q[N];
set<Node>st;
signed main(){
n=read();
For(i,1,n){
c[i].x=read(),c[i].y=read(),c[i].r=read();
q[(i<<1)-1]={1,c[i].x-c[i].r,i}; //插入上下圆弧
q[i<<1]={-1,c[i].x+c[i].r,i};
}
sort(q+1,q+(n<<1)+1);
For(i,1,(n<<1)){
lx=q[i].x;
if(q[i].type==1){
set<Node>::iterator it=st.insert(Node(1,q[i].id)).fi;
if(it==st.begin()) d[q[i].id]=1; //是最外层的
else{
it--;
d[q[i].id]=d[(*it).id]^((*it).type<0); //判断包含/并列关系
}
ans+=(d[q[i].id]?1:-1)*sqr(c[q[i].id].r);
st.insert(Node(-1,q[i].id));
}
else st.erase({1,q[i].id}),st.erase({-1,q[i].id});
}
printf("%lld",ans);
return 0;
}