luogu P3268 [JLOI2016]圆的异或并

https://www.luogu.com.cn/problem/P3268
是一道帮助理解扫描线的好题
首先意识到这题的圆是只有包含和相离两种状态的,所以考虑扫描线
那么圆形怎么扫描线呢?
考虑有一条从左往右的扫描线,一个圆形出现的区间就是圆心的 [ x i − r i , x i + r i ] [x_i-r_i,x_i+r_i] [xiri,xi+ri]
然后用呢一个数据结构维护y轴,这里我用set
扫到左端点时候就把这个圆的下端点 y i − r i y_i-r_i yiri加入set,扫到右端点的时候就把上端点加入
在加入下端点的时候就找它的前驱 j j j如果 j j j是上端点说明它们是同层的,否则说明它被 j j j包含,然后就可以根据每个圆的层数进行奇加偶减即可
code:

#include<bits/stdc++.h>
#define N 400050
using namespace std;
const double eps = 1e-3;
struct PT {
	double x, y, r;
} a[N];
double nowx;
struct cir {
	int o, id;
	double calc() const {
		double dy = sqrt(a[id].r * a[id].r - (nowx - a[id].x) * (nowx - a[id].x));
	//	printf("*%lf %lf %lf   %lf*\n", dy, a[id].r * a[id].r, (nowx), a[id].y + (double) o * (dy + eps));
		return a[id].y + (double) o * (dy + eps);
	}
	bool operator < (const cir & o) const {
		return calc() - o.calc() < - eps;
	}
};
set<cir> S;
struct SG {
	int o;
	double x;
	int id;
} sg[N << 1];
int cmp(SG x, SG y) {
	return x.x < y.x;
}
int n, cnt[N], sz;

int main() {
//	freopen("a.in","r",stdin);
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) {
		scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].r);
		sg[++ sz] = (SG){1, a[i].x - a[i].r, i};
		sg[++ sz] = (SG){- 1, a[i].x + a[i].r, i};
	}
	sort(sg + 1, sg + 1 + sz, cmp);
	long long ans = 0;
	for(int i = 1; i <= sz; i ++) {
		nowx = sg[i].x; int id = sg[i].id; 
		//printf("%lf",nowx);
		if(sg[i].o == 1) {
			set<cir>::iterator it;
			it = S.insert((cir){1, id}).first;//printf("*%d  %d   %lf\n", id, (*it).id, (*it).calc());
			if(it == S.begin()) cnt[id] = 1;
			else {
				-- it; //printf("*%d  %d   %lf", id, (*it).id, (*it).calc());
				if((*it).o == -1) cnt[id] = cnt[(*it).id] ^ 1;
				else cnt[id] = cnt[(*it).id];
			}
			if(cnt[id]) ans += a[id].r * a[id].r; else ans -= a[id].r * a[id].r;
			S.insert((cir){- 1, id});
		} else S.erase((cir){1, id}), S.erase((cir){-1, id});
		
	}
//	int ss = 0;
//	for(int j = 1; j <= n; j ++) ss += cnt[j];//printf("%d ", cnt[j]); printf("\n");
	printf("%lld", ans);
	return 0;
}

posted @ 2021-07-12 09:15  lahlah  阅读(35)  评论(0编辑  收藏  举报