首页 > 代码库 > POJ 2155 Matrix 【二维树状数组】

POJ 2155 Matrix 【二维树状数组】

题目链接: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;
}