题目链接:POJ 2155 Matrix
楼教主出的题。
【题目大意】
给你你 N x N的矩形区域, 开始时每个点的值都为0
有两种操作
C x1 y1 x2 y2 将区域 x1 到 x2 y1 到 y2 围成的矩形区域的值翻转 (1变0 ,0变1);
Q x1,y1,输出 (x1,y1)的值;
典型的区间更新,点查找的题目
相应的一维树状数组题目HDU 1556 Color the ball
在更新的时候同样是先把大区间更新,再把多更新的区间还原。
因为所有节点的值都是0,1 所以我们更新时只用++ ,最后 取余2 就可以了。
和一维树状数组点查询 同样的原理, 统计时向”左“统计翻转次数。
【源代码】
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,q;
const int maxn = 1010;
int s[maxn][maxn];
int map[maxn][maxn];
int lowbit(int x){
return x&(-x);
}
void update(int x,int y){
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j)){
s[i][j]++;
}
}
int query(int x,int y){
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
for(int j=y;j>0;j-=lowbit(j)){
ans+=s[i][j];
}
}
return ans%2; //取模
}
int main(){
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++){
if(i!=1)
puts("");
scanf("%d%d",&n,&q);
memset(s,0,sizeof(s)); //不要忘记初始化
char cmd;
int x1,y1,x2,y2;
while(q--){
scanf(" %c",&cmd);
if(cmd=='C'){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
update(x1,y1); //更新大区间
update(x2+1,y1); //抵消掉多余的更新
update(x1,y2+1); //抵消掉多余的更新
update(x2+1,y2+1); //抵消掉多余的更新
}
else{
scanf("%d%d",&x1,&y1);
printf("%d\n",query(x1,y1)); //直接输出向左上方查询的值
}
}
}
return 0;
}