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; } }
标签:y2,树状,int,修改,x2,2155,POJ,y1,x1 来源: https://www.cnblogs.com/liyexin/p/13019757.html