poj2155(二维树状数组)
我们知道二维数组,那么二维树状数组也是一个道理。
第一维维护的是行,第二维维护的是行中的具体元素。
空间O(n2),单次操作时间O((logn)2)
另本题实现的区间修改和单点查询需要用到差分的思想:
看一维的情况,假设a数组:1,2,3,4,5
b[i]=a[i]-a[i-1]:1,1,1,1,1
则有a[i]=b[i]+b[i-1]+...+b[1]。
对a数组的中间三个数加x,则b[i]:1,1+x,1,1,1-x,发现即只要b[l]+x,b[r+1]-x即可
那么我们用树状数组维护b[i]数组即可。
http://poj.org/problem?id=2155
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<map> 8 #include<vector> 9 #include<bitset> 10 #define N 1005 11 using namespace std; 12 int sum[N][N],n; 13 inline int lowbit(int x) 14 { 15 return (x&-x); 16 } 17 void change(int x,int y,int delta) 18 { 19 int ty=y; 20 while(x<=n) 21 { 22 y=ty; 23 while(y<=n) 24 { 25 sum[x][y]+=delta; 26 y+=lowbit(y); 27 } 28 x+=lowbit(x); 29 } 30 } 31 int query(int x,int y) 32 { int ty=y,ans=0; 33 while(x>0) 34 { y=ty; 35 while(y>0) 36 { 37 ans+=sum[x][y]; 38 y-=lowbit(y); 39 } 40 x-=lowbit(x); 41 } 42 return ans; 43 } 44 int main() 45 { 46 int Case; 47 cin>>Case; 48 while(Case--) 49 { 50 memset(sum,0,sizeof sum); 51 cin>>n; 52 int q; 53 cin>>q; 54 while(q--) 55 { 56 char s[5]; 57 scanf("%s",s); 58 if(s[0]=='C') 59 { 60 int x1,x2,y1,y2; 61 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 62 change(x1,y1,1); 63 change(x1,y2+1,-1); 64 change(x2+1,y1,-1); 65 change(x2+1,y2+1,1); 66 } 67 if(s[0]=='Q') 68 { int x,y; 69 scanf("%d%d",&x,&y); 70 printf("%d\n",query(x,y)&1); 71 } 72 } 73 if(Case!=0) 74 printf("\n"); 75 } 76 77 78 return 0; 79 }