POJ2155 - Matrix

文章目录

题目

给你一个二维矩阵,初始化为0,然后可以进行两次操作:
C:x,y,x1,y2 对该小矩阵内的数进行取反
Q:查询某个点是0还是1

题解:

C是区间修改,Q是单点查询,
我们将二维矩阵先简化成一维矩阵的情况,C是对一段区域[l,r]取反,我们没有必要对这段区域全部操作,我们只需要对点l和点(r+1)分别加1即可,然后查询k时,我们只需要求出k的前缀和,然后mod2即可
为什么?

如果,当k1在区间[l,r]里,k的前缀和比之前就了一个1,mod2之后就说明k1被改变了一次;当k2在[l,r]之前,没有影响;在[l,r]之后,k3的前缀和比原本多了2(l和r+1点分别多贡献一),mod 2之后就没影像了,相当于没改变
也就是当k的前缀和比原本多出奇数时,说明值比原先发生改变,否则就没有。
所以我们对于一个区间[L,R],我们只需要改变点(L)和点(R+1),
同样回到本题,二维矩阵也是这样,
左上角是x1,y1,右下角是x2,y2
a[x1][y1]+1,
a[x2+1][y2]+1
a[x1][y2+1]+1,
a[x2+1][y1+1]+1
原理和上面一样
详细看图

然后用前缀和和二维树状数组来维护,单点更改,单点查询

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=2000;
int a[maxn][maxn];
int n;
string s;
int lowbit(int x)
{
   
	return x&(-x);
}
void add(int x,int y,int w)
{
   
	for(int i=x;i<=n;i+=lowbit(x))
	{
   
		for(int j=y;j<=n;j+=lowbit(y))
		{
   
			a[i][j]+=w;
		}
	}
}
int sum(int x,int y)
{
   
	int ans=0;
	for(int i=x;i;i-=lowbit(i))
	{
   
		for(int j=y;j;j-=lowbit(j))
		{
   
			ans+=a[i][j];
		}
	}
	return ans;
}
int main()
{
   
	int t;
	cin>>t;
	int x1,y1,x2,y2;
	while(t--)
	{
   
		int k;
		cin>>n>>k;
		memset(a,0,sizeof(a));
		for(int i=1;i<=k;i++)
		{
   
			cin>>s;
			if(s[0]=='C')
			{
   
				cin>>x1>>y1>>x2>>y2;
				add(x1,y1,1);
				add(x2+1,y1,1);
				add(x1,y2+1,1);
				add(x2+1,y2+1,1);
			}
			else 
			{
   
				int x,y;
				cin>>x>>y;
				cout<<sum(x,y)%2<<endl;
			}
		}
	}
}