题目链接: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 【二维树状数组】
时间: 2024-10-15 20:53:09