题意:
给一个n*n的矩阵,初始全是白色,进行m次操作,每次操作是让一个子矩阵的颜色翻转,求最后有几个黑色的方格。

题解:

每行分别处理,将一个子矩阵拆成两条线段,分别是上底和下底,然后按照线段的高度排序。

每到一行,将所有高度等于该行的下底的线段加入线段树中,表示对这个线段进行翻转,更新答案,最后将所有高度等于该行的上底的线段加入线段树中,表示对这个线段进行翻转。

 

代码:

#include<bits/stdc++.h>
#include<hash_map>
#define N 10010
#define INF 0x3f3f3f3f
#define eps 1e-10
#define pi 3.141592653589793
#define LL long long
#define pb push_back
#define cl clear
#define si size
#define lb lowwer_bound
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;

struct Seg
{
	int h,l,r,flag;
	bool operator < (const Seg &z) const
	{
		if (h==z.h) return flag>z.flag;
		return h<z.h;
	}
}seg[N<<1];

int mk[N<<2],sum[N<<2];

inline void nodeupdata(int x,int l,int r)
{
	mk[x]^=1;
	sum[x]=(r-l+1)-sum[x];
}

inline void pushdown(int x,int l,int r)
{
	if (!mk[x]) return;
	int t=(l+r)>>1;
	nodeupdata(x<<1,l,t);
	nodeupdata(x<<1|1,t+1,r);
	mk[x]=0;
}

void updata(int x,int l,int r,int fl,int fr)
{
	if (l==fl && r==fr)
	{
		nodeupdata(x,l,r);
		return;
	}
	pushdown(x,l,r);
	int t=(l+r)>>1;
	if (fr<=t) updata(x<<1,l,t,fl,fr);else
	if (fl>t) updata(x<<1|1,t+1,r,fl,fr);else
	{
		updata(x<<1,l,t,fl,t);
		updata(x<<1|1,t+1,r,t+1,fr);
	}
	sum[x]=sum[x<<1]+sum[x<<1|1];
}

int main()
{
	int T;
	sc(T);
	while(T--)
	{
	    mem(mk);
	    mem(sum);
		int n,m;
		scc(n,m);
		for (int i=1;i<=m;i++)
		{
			int x1,x2,y1,y2;
			scc(x1,x2);scc(y1,y2);
			seg[i*2-1]=Seg{y1,x1,x2,1};
			seg[i*2]=Seg{y2,x1,x2,-1};
		}
		sort(seg+1,seg+m*2+1);
		int ans=0; int j=1; m<<=1;
		for (int i=1;i<=n;i++)
		{
			while(j<=m && seg[j].h<=i && seg[j].flag==1)
			{
				updata(1,1,n,seg[j].l,seg[j].r);
				j++;
			}
			ans+=sum[1];
			while(j<=m && seg[j].h<=i)
			{
				updata(1,1,n,seg[j].l,seg[j].r);
				j++;
			}
		}
		printf("%d\n", ans );
	}
	return 0;
}