POJ2155Matrix——二维树状数组

题目传送门
本题大意就是给定一个n*n的矩阵,矩阵里的每一个数要么是0,要么是1。有两种操作,C操作是将区间[(x1,y1),(x2,y2)]中所有的数反转(0变1,1变0),Q操作是查询f[x][y]的数值。
我们依然用二维树状数组维护。由于树状数组进行单点查询区间修改时运用了差分思想。而这里是0和1的改变,所以我们很容易想到^的差分。同计f[x][y]时只要将区间[(1,1),(x,y)]里面所有的1异或起来,如果是1,就输1;否则输出0即可。
那么我们怎么差分呢?最先想到的思路就是将f[x1,y1]、f[x2+1,y2+1]这两个点都^1。但是这样就真行了嘛?看看下面的例子:
我们修改的是红色的区间,在红色的左上角和右下角打上标记。那么会发现绿色的区域都是0。但是两块黄色的区域本来应该是0,但是算下来的结果是1。所以这种思路是错的。

这里写图片描述

但是又不是全错,我们只要考虑怎么消除这两块黄色,并且不影响其它颜色块即可。我们发现,在红色区域的剩下的两个点也打上标记即可。即f[x1,y2+1],f[x2+1,y1]也打上标记即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int T,n,q,f[1005][1005];
int lowbit(int x){return x&-x;}
char c;
void add(int x,int y,int ad){
    for(int i=x;i<=n;i+=lowbit(i))
     for(int j=y;j<=n;j+=lowbit(j)){
        f[i][j]^=ad;
     }
}
int getsum(int x,int y){
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
     for(int j=y;j;j-=lowbit(j)){
        ans^=f[i][j];
     }
    return ans;
}
int main()
{
    T=read();
    while(T--){
        memset(f,0,sizeof(f));
        n=read();q=read();
        for(int i=1;i<=q;i++){
            cin>>c;
            if(c=='C'){
                int x=read(),y=read(),u=read(),v=read();
                add(x,y,1);add(x,v+1,1);add(u+1,y,1);add(u+1,v+1,1);
            }
            if(c=='Q'){
                int x=read(),y=read();
                printf("%d\n",getsum(x,y));
            }
        }
        if(T) puts("");
    }
    return 0;
}
由于没有看到输出要求里的"There is a blank line between every two continuous test cases. "导致我PE了3次,GTMDPOJ

猜你喜欢

转载自blog.csdn.net/stevensonson/article/details/80904641