BZOJ4561 [JLoi2016]圆的异或并

这题现场的时候n=30000部分分居然是给暴力的,我分段写的个乱搞40分结果暴力都60分,差评

正解:

首先可知一个圆被奇数个圆套则答案减去其面积,被偶数个套则加上其面积,然后我们维护一个垂直于x轴扫描线,从左向右扫,每个圆拆成加入和删除两个事件,由于圆和圆不相交,所以一个圆可以看成一个括号,整个扫描线上是一个括号序列,而且随扫描线当前x增加括号之间相对顺序不变(扫描线都是某些相对顺序不变,然后维护当前x?)

因为圆和圆不相交,所以加入和删除的时候肯定都是对最内层的括号操作,只会影响到自己,所以我们只需要对扫描线上每个点记录他属于哪个圆(算出当前x下y坐标),是左括号还是右括号和外边套了几层(在新加入括号的时候用这两个算出新加的括号是第几层),然后在加入一对括号的时候查询他外面套了几层更新答案即可

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
double nowx;
int X[MAXN],Y[MAXN],R[MAXN];
struct cir{
	bool ud;
	int bel;
	int c;
	cir(){
		
	}
	cir(int _ud,int _bel,int _c=0){
		ud=_ud;
		bel=_bel;
		c=_c;
	}
	inline double y(int x){
		double re=Y[bel];
		if(ud){
			re+=sqrt(1.0*R[bel]*R[bel]-1.0*(x-X[bel])*(x-X[bel]));
		}else{
			re-=sqrt(1.0*R[bel]*R[bel]-1.0*(x-X[bel])*(x-X[bel]));
		}
		return re;
	}
	friend bool operator <(cir x,cir y){
		return fabs(x.y(nowx)-y.y(nowx))>eps?x.y(nowx)>y.y(nowx):x.ud>y.ud;
	}
};
struct evt{
	int x;
	int v;
	friend bool operator <(evt x,evt y){
		return x.x<y.x;
	}
};
int n;
set<cir>wzh;
evt e[MAXN*2];
int tot;
ll ans;
int main(){
	int i;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d%d%d",&X[i],&Y[i],&R[i]);
		e[++tot].x=X[i]-R[i];
		e[tot].v=i;
		e[++tot].x=X[i]+R[i];
		e[tot].v=-i;
	}
	R[0]=INF;
	nowx=-INF;
	wzh.insert(cir(1,0,-1));
	wzh.insert(cir(0,0,-1));
	sort(e+1,e+tot+1);
	int c;
	for(i=1;i<=tot;i++){
		nowx=e[i].x;
		if(e[i].v>0){
			cir t=*wzh.upper_bound(cir(0,e[i].v));
			if(t.ud){
				c=t.c;
			}else{
				c=t.c+1;
			}
			if(c&1){
				ans-=(ll)R[e[i].v]*R[e[i].v];
			}else{
				ans+=(ll)R[e[i].v]*R[e[i].v];
			}
			wzh.insert(cir(1,e[i].v,c));
			wzh.insert(cir(0,e[i].v,c));
			
		}else{
			e[i].v=-e[i].v;
			wzh.erase(cir(1,e[i].v,c));
			wzh.erase(cir(0,e[i].v,c));
		}
	}
	printf("%lld\n",ans);
	return 0;
}

/*

*/


你可能感兴趣的:(BZOJ4561 [JLoi2016]圆的异或并)