[JLOI2016]圆的异或并

Problem

平面上给定若干互不相交的圆(仅有包含和相离两种关系),求圆的异或面积(覆盖奇数次的区域贡献答案)除以 (pi)

(nleq 2 imes 10^5,|x_i|,|y_i|leq 10^8)

Sol & Code

扫描线从左往右扫。由于圆和圆之间不相交,与扫描线交点位置关系不变(上半圆看成左括号,下半圆看成右括号,将会一直满足括号序列合法)。然后加入一个圆就维护下新加进来的两个括号。使用 set 维护。复杂度 (mathcal O(nlog n))

#include <bits/stdc++.h>
#define pb push_back
using std::vector; using std::set; using std::sort;
typedef long long LL;
typedef double DB;
const int N = 200005;
const DB eps = 1e-7;
int n, x[N], y[N], r[N], tag[N];
struct node1 { int pos, id; };
vector<node1> v;
bool cmp(node1 a, node1 b) { return a.pos < b.pos; }
int X;
LL sqr(int x) { return 1LL * x * x; }
struct node2 {
	int id, ty;
	DB calc() { return y[id] + (ty == 1 ? 1 : -1) * sqrt(sqr(r[id]) - sqr(X - x[id]) + eps); }
	friend bool operator < (node2 a, node2 b) { return a.calc() < b.calc() - eps; }
};
set<node2> s;
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d%d", &x[i], &y[i], &r[i]);
		v.pb((node1){x[i] - r[i], i}), v.pb((node1){x[i] + r[i], -i});
	}
	sort(v.begin(), v.end(), cmp);
	for (int i = 0; i < v.size(); i++) {
		X = v[i].pos;
		if (v[i].id > 0) {
			set<node2>::iterator it = s.insert((node2){v[i].id, 1}).first;
			if (it != s.begin()) {
				--it;
				if (it->ty == -1) tag[v[i].id] = tag[it->id] ^ 1;
				else tag[v[i].id] = tag[it->id];
			} else tag[v[i].id] = 1;
			s.insert((node2){v[i].id, -1});
		} else
			s.erase((node2){-v[i].id, 1}), s.erase((node2){-v[i].id, -1});
	}
	LL ans = 0;
	for (int i = 1; i <= n; i++) ans += (tag[i] ? 1 : -1) * sqr(r[i]);
	printf("%lld", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/ac-evil/p/14490004.html