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;}}}
}