Description
在平面直角坐标系中给定N个圆。已知这些圆两两没有交点,即两圆的关系只存在相离和包含。求这些圆的异或面积并。异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个圆内则不考虑。
第一行包含一个正整数N,代表圆的个数。接下来N行,每行3个非负整数x,y,r,表示一个圆心在(x,y),半径为r的圆。保证|x|,|y|,≤10^8,r>0,N≤200000
Output
仅一行一个整数,表示所有圆的异或面积并除以圆周率Pi的结果。
2
0 0 1
0 0 2
Sample Output
3
Solution
来一条扫描线,从左向右扫描,遇到一个圆的左边就把这个圆的上半部分和下半部分压入一个set,然后看它下半部分的严格后继是什么,如果是一个下半圆,那么这个下半圆和这个圆贡献不同,否则贡献相同。
如何比较两个圆?
来自同一个圆时,下>上
相离时,纵坐标大的越小
包含时,上下半圆顶点越大的越小
(其实是相反的问题,YY一下。。。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;
typedef long long LL;
const int INF=1000000007;
const int N=200005;
struct Cir{LL x,y,r;}c[N];
struct node{int id;};
inline int getint() {
int r = 0; bool b = true; char c = getchar();
while ('0' > c || c > '9') {if (c == '-') b = false; c = getchar();}
while ('0' <= c && c <= '9') {r = r * 10 + (c - '0'); c = getchar();}
if (b) return r;
return -r;
}
inline bool operator < (node o1,node o2) {
if (abs(o1.id)==abs(o2.id)) return o1.id>o2.id;
Cir c1=c[abs(o1.id)],c2=c[abs(o2.id)];
if ((c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y)>(c1.r+c2.r)*(c1.r+c2.r)) return c1.y>c2.y;
LL p1=c1.y+c1.r*o1.id/abs(o1.id);
LL p2=c2.y+c2.r*o2.id/abs(o2.id);
return p1>p2;
}
inline bool cmp(int o1,int o2) {
LL p1=c[abs(o1)].x-c[abs(o1)].r*(LL)(abs(o1)/o1);
LL p2=c[abs(o2)].x-c[abs(o2)].r*(LL)(abs(o2)/o2);
return (p1<p2)||((p1==p2)&&(o1<o2));
}
set <node> s;
set <node>::iterator it;
int n,b[N*2];
LL ans,gx[N];
int main()
{n=getint();
for (int i=1; i<=n; i++)
{c[i].x=getint();c[i].y=getint();c[i].r=getint();
b[i]=i;b[i+n]=-i;
}
sort(b+1,b+1+2*n,cmp);
c[n+1].x=c[n+1].y=0;c[n+1].r=INF;gx[n+1]=-1;
s.insert((node) {n+1});
s.insert((node) {-(n+1)});
for (int i=1; i<=2*n; i++) {
if (b[i]>0) {
it=s.upper_bound((node){-b[i]});
if ((*it).id<0) gx[b[i]]=-gx[-(*it).id];
else gx[b[i]]=gx[(*it).id];
s.insert((node){b[i]});
s.insert((node){-b[i]});
} else {
s.erase((node){b[i]});
s.erase((node){-b[i]});
}
}
for (int i = 1; i <= n; ++i) ans += gx[i] * c[i].r * c[i].r;
printf("%lld",ans);
}
|