2017acm香港区域赛 Black and White

匿名 (未验证) 提交于 2019-12-02 22:56:40

题目:

有一个初始颜色全为白色的n*n的棋盘,每次选一个长方形区域反转颜色,问最后会有几个黑色格子。n,k<=10000

分析:

和扫描线求面积并一样。记录每条横边,向x轴投影。只不过不区分上边和下边。按高度排序后,对于每条边,向x轴投影,将投影的区间进行一次 xor 1 的操作。所以线段树维护区间异或操作,然后每次询问区间和。

代码:

#include<bits/stdc++.h> #define lson rt<<1,l,(l+r)/2 #define rson rt<<1|1,(l+r)/2+1,r using namespace std; const int MAXN = 1e4+5; int n,k,cnt; struct Edge { 	int l,r,h; 	bool operator < (const Edge &e) const { 		return h < e.h; 	} }e[MAXN<<1]; struct Seg_Tree{ 	int sum[MAXN << 2], tag[MAXN<<2]; 	void build() { 		memset(sum,0,sizeof sum); 		memset(tag,0,sizeof tag); 	} 	void pushup(int rt) { 		sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 	} 	void pushdown(int rt,int l,int r) { 		if(tag[rt]){ 			tag[rt<<1] ^= tag[rt]; 			tag[rt<<1|1] ^= tag[rt]; 			sum[rt<<1] = (l+r)/2 - l + 1 - sum[rt<<1]; 			sum[rt<<1|1] = r - (l+r)/2 - sum[rt<<1|1]; 			tag[rt] = 0; 		} 	} 	void update(int L,int R,int rt,int l,int r) { 		if(L<=l && R>=r){ 			tag[rt] ^= 1; 			sum[rt] = (r-l+1) - sum[rt]; 			return; 		} 		pushdown(rt,l,r); 		if(L<=(l+r)/2)	update(L,R,lson); 		if(R>(l+r)/2) update(L,R,rson); 		pushup(rt); 	} }t; int main() { 	ios::sync_with_stdio(false); 	int T; 	cin >> T; 	while(T--) { 		cin >> n >> k; 		cnt = 0; 		for(int i=0;i<k;i++){ 			int xlow,xhigh,ylow,yhigh; 			cin >> xlow >> xhigh >> ylow >> yhigh; 			e[++cnt] = {xlow,xhigh,ylow}; 			e[++cnt] = {xlow,xhigh,yhigh+1}; 		} 		sort(e+1,e+cnt+1); 		int ans = 0; 		t.build(); 		for(int i=1;i<cnt;i++) { 			t.update(e[i].l,e[i].r,1,1,1e4+2); 			ans += t.sum[1]*(e[i+1].h-e[i].h); 		} 		cout << ans << endl; 	} 	return 0; } 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!