【BZOJ4561】[JLoi2016]圆的异或并
把圆拆成上下两个圆弧,因为不存在相交关系,圆弧直接的上下关系是不变的。
用set维护这些圆弧,插入的时候upper_bound一下,如果找到的是上圆弧,就是我外面的第一个圆,否则我外面的第一个圆就是这个下圆弧外面的第一个圆。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=400007;
typedef long long LL;
typedef double db;
using namespace std;
int n,cnt,f[N];
db x[N],y[N],r[N],now;
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
struct node {
int id,f;
node(){}
node(int id,int f):id(id),f(f){}
friend bool operator <(const node&A,const node&B) {
return x[A.id]+A.f*r[A.id]<x[B.id]+B.f*r[B.id];
}
}q[N];
struct bow {
int id,f;
bow(){}
bow(int id,int f):id(id),f(f){}
};
bool operator <(const bow&A,const bow&B) {
db y1=(db)y[A.id]+(db)A.f*sqrt(r[A.id]*r[A.id]-(now-x[A.id])*(now-x[A.id]));
db y2=(db)y[B.id]+(db)B.f*sqrt(r[B.id]*r[B.id]-(now-x[B.id])*(now-x[B.id]));
return y1==y2?A.f<B.f:y1<y2;
}
set<bow>s;
#define IT set<bow>::iterator
//#define DEBUG
int main() {
#ifdef DEBUG
freopen("4561.in","r",stdin);
freopen("4561.out","w",stdout);
#endif
read(n);
For(i,1,n) { read(x[i]); read(y[i]); read(r[i]); q[++cnt]=node(i,-1); q[++cnt]=node(i,1); }
sort(q+1,q+cnt+1);
For(i,1,cnt) {
now=x[q[i].id]+q[i].f*r[q[i].id];
if(q[i].f==-1) {
IT it=s.upper_bound(bow(q[i].id,1));
if(it!=s.end()) {
bow tp=*it;
if(tp.f==-1) f[q[i].id]=f[tp.id];
else f[q[i].id]=-f[tp.id];
}
else f[q[i].id]=1;
s.insert(bow(q[i].id,1)); s.insert(bow(q[i].id,-1));
}
else s.erase(bow(q[i].id,1)),s.erase(bow(q[i].id,-1)) ;
}
db ans=0;
For(i,1,n)
ans+=r[i]*r[i]*f[i];
printf("%lld\n",(LL)ans);
return 0;
}
/*
5
-153 -765 50
-51 -765 50
0 867 50
0 969 50
0 969 47
*/