POJ--2155(二维树状数组区间更新)

地址:http://poj.org/problem?id=2155

题意:

n*n的矩阵。初始为0。

C:x1,y1,x2,y2:围成的矩阵内数字反转:0/1

Q:x,y:查询a[x][y]为多少

解析:

还是差分

先把它想成一维:修改[l,r]:那么我们就更新d[L]+1,d[R+1]+1;

都+1的原因是,由于是取反,d[R+1]后面再加个1,就可以回复原状。

接下来是二维:

 

修改(x1,y1),那么从它到右下角,修改次数均+1 。涂颜色的部分是多余的部分,需要把它们回复原样。

修改(x2+1,y1),(x1,y2+1),那么从它俩到右下角,修改次数加上上一步,为+2,也是恢复了原样。

而(x1+1,y2+1)到右下角的部分+3了,要想恢复,需要再修改一次,变为偶数次修改+4,即恢复原样。

由于本质上是个差分,所以要询问一个点,直接

void update(int x,int y)
{
    for(int i=x;i<maxn;i+=lowbit(i))
        for(int j=y;j<maxn;j+=lowbit(j))
            c[i][j]++;
}

一路加下来,得到的是a[i][j]本身的修改次数。

总的ac代码,输出格式注意一下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1005;
int c[maxn][maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y)
{
    for(int i=x;i<maxn;i+=lowbit(i))
        for(int j=y;j<maxn;j+=lowbit(j))
            c[i][j]++;
}
int getsum(int x,int y)
{
    int sum=0;
    for(int i=x;i>=1;i-=lowbit(i))
    {
        for(int j=y;j>=1;j-=lowbit(j))
            sum+=c[i][j];
    }
    return sum;
}
int getall(int x1,int y1,int x2,int y2)
{
      return getsum(x2,y2)-getsum(x1-1,y2)-getsum(x2,y1-1)+getsum(x1-1,y1-1);
}
int main()
{
      int t;
      cin>>t;
      while(t--)
      {
          int n,k;
         scanf("%d%d",&n,&k);
         memset(c,0,sizeof(c));
         char s[12];
        while(k--)
         {
             scanf("%s",s);
            if(s[0]=='Q')
            {
                int i , j ;
                scanf("%d%d",&i,&j);
                cout<<getsum(i,j)%2<<endl;
            }    
            else
            {
                int x1,y1,x2,y2;
                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);
            }
        }
        if(t>0)
            cout<<endl;
     }
}

 

posted @ 2020-05-31 16:47  liyexin  阅读(177)  评论(0编辑  收藏  举报