题目链接:http://poj.org/problem?id=2155
题目大意:给出一个N*N的0矩阵,下面给出两种指令:1. 给出的第一个数据为‘C’,再给出四个整形数据,x1,y1,y1,y2,对以(x1,y1)(x2,y2)分别为左上角和右下角坐标的矩阵内的元素进行反转(0变1,1变0) 2. 给出的第一个数据为‘Q’,再给出两个数据,x,y,然后输出此时这个坐标上的元素。
这题用二维树状数组解,树状数组能够对某区间更新所有元素的和,树状数组维护的是c[1][1]到c[i][j]之内的所有元素的和,更新的也是这个区间和。因为这里元素类型只有0,1,所以对于区间和来说只有奇偶之分,更新偶数次相当于没有改变其有效值。所以更新(x1,y1)(x2,y2)内的元素,只需要Update(x2,y2),Update(x1-1,y2),Update(x2,y1-1),Update(x1-1,y1-1)这几个语句分别执行一次即可,最后输出区间和模2就能得到答案。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1001
using namespace std;
int c[N][N];
int n;
int Lowbit(int x)
{
return x & (-x);
}
void Update(int x,int y){
for(int i=x;i>0;i-=Lowbit(i))
for(int j=y;j>0;j-=Lowbit(j))
c[i][j]++;
}
int Getsum(int x,int y){
int ret=0;
for(int i=x;i<=n;i+=Lowbit(i))
for(int j=y;j<=n;j+=Lowbit(j))
ret+=c[i][j];
return ret;
}
int main()
{
int x;
scanf("%d",&x);
while(x--)
{
memset(c,0,sizeof(c));
int T;
int x,y,x1,y1,x2,y2;
char ch[2];
scanf("%d%d",&n,&T);
while (T--)
{
scanf("%s",ch);
if(ch[0]=='C')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
Update(x2,y2);
Update(x1-1,y2);
Update(x2,y1-1);
Update(x1-1,y1-1);
}
else if(ch[0]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",Getsum(x,y)%2);
}
}
printf("\n");
}
return 0;
}
POJ 2155 Matrix 【二维树状数组】,布布扣,bubuko.com
原文地址:http://blog.csdn.net/u013912596/article/details/33759555