题目:POJ2155.
题目大意:对一个矩阵支持:
1.格式C x1 y1 x2 y2,表示将左上角为(x1,y1),右下角为(x2,y2)的矩阵全部取反,即0变1,1变0.
2.格式Q x y,表示查询位置(x,y)的值.
这道题是二维树状数组的裸题啊.
我们可以先写一颗树状数组,然后这棵树状数组的每个节点都是一颗树状数组来维护二维树状数组.
那么怎么样写的简洁一些呢,我们可以把树状数组封装一下.
现在我们讨论一下如何维护这个矩阵.
我们先考虑是序列的情况,那我们可以记录一下每一个点的信息都是它翻转了几次,再做一下差分,我们就可以维护了.
但是由于我们只需要维护奇偶性,所以我们现在只维护每个节点是否要翻转,这个时候我们再做一下差分,但这时候的差分数组就表示后面的元素是否要再一次翻转.
也就是说我们修改一个序列的时候就是直接修改第x元素取反,第y+1个元素也取反.
扩展到二维就是对(x1,y1),(x1,y2+1),(x2+1,y1),(x2+1,y2+1)分别取反,查询的时候直接查询前缀异或就可以了.
代码如下:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define Abigail inline void
#define rep(i,j,k) for (int i=j;i<=k;i++)
typedef long long LL;
const int N=1000;
const int INF=(1<<30)-1+(1<<30);
int a[N+9][N+9],n,q;
int lowbit(int x){
return x&-x;
}
void change(int x,int y){
for (int i=x;i<=n;i+=lowbit(i))
for (int j=y;j<=n;j+=lowbit(j))
a[i][j]^=1;
}
int query(int x,int y){
int sum=0;
for (int i=x;i>0;i-=lowbit(i))
for (int j=y;j>0;j-=lowbit(j))
sum^=a[i][j];
return sum;
}
void rc(char &c){
c=getchar();
while (c<'A'||c>'Z') c=getchar();
}
Abigail into(){
memset(a,0,sizeof(a));
scanf("%d%d",&n,&q);
}
Abigail work(){
char c;
int x1,y1,x2,y2;
for (int i=1;i<=q;i++){
rc(c);
if (c=='C'){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
change(x1,y1);change(x1,y2+1);change(x2+1,y1);change(x2+1,y2+1);
}else{
scanf("%d%d",&x1,&y1);
printf("%d\n",query(x1,y1));
}
}
printf("\n");
}
Abigail outo(){
}
int main(){
int T=0;
scanf("%d",&T);
while (T--){
into();
work();
outo();
}
return 0;
}