题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1892
题目大意:有很多方格,每个方格对应的坐标为(I,J),刚开始时每个格子里有1本书,然后让你统计一片区域有多少本书,还可以增加书和减少,移动书。
解题思路:
和一维树状数组没撒子区别。一维扩展到二维而已。
需要注意的两点是:1.x,y坐标从0开始,所以存储更新的时候坐标分别加1进行更新。因为0坐标会进入死循环。
2.区间求和的时候bit数组里面存的是它整个左下角的和,所以还要进行操作(即下面的find函数)让它表示的此位置的数目。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn=1005; 8 int bit[maxn][maxn]; 9 10 int lowbit(int x) 11 { 12 return x&(-x); 13 } 14 15 void add(int x, int y, int val) 16 { 17 while(x<maxn) 18 { 19 int t=y; 20 while(t<maxn) 21 { 22 bit[x][t]+=val; 23 t+=lowbit(t); 24 } 25 x+=lowbit(x); 26 } 27 } 28 29 int sum(int x, int y) 30 { 31 int ans=0; 32 while(x>0) 33 { 34 int t=y; 35 while(t>0) 36 { 37 ans+=bit[x][t]; 38 t-=lowbit(t); 39 } 40 x-=lowbit(x); 41 } 42 return ans; 43 } 44 45 int find(int x,int y) 46 { 47 return sum(x,y)-sum(x-1,y)-sum(x,y-1)+sum(x-1,y-1); 48 } 49 50 int main() 51 { 52 int T, n, x1, x2, y1, y2, a, tcase=0; 53 char ch[5]; 54 cin >> T; 55 while(T--) 56 { 57 printf("Case %d:\n",++tcase); 58 scanf("%d",&n); 59 memset(bit,0,sizeof(bit)); 60 for(int i=1; i<maxn; i++) 61 for(int j=1; j<maxn; j++) 62 add(i,j,1); 63 for(int i=0; i<n; i++) 64 { 65 scanf("%s",ch); 66 if(ch[0]=='A'||ch[0]=='D') 67 { 68 scanf("%d%d%d",&x1,&y1,&a); 69 if(ch[0]=='D') 70 a=-min(a,find(x1+1,y1+1)); 71 add(x1+1,y1+1,a); 72 } 73 else if(ch[0]=='M') 74 { 75 scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&a); 76 int tmp=min(a,find(x1+1,y1+1)); 77 add(x1+1,y1+1,-tmp); 78 add(x2+1,y2+1,tmp); 79 } 80 else 81 { 82 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 83 if(x1>x2) swap(x1,x2); 84 if(y1>y2) swap(y1,y2); 85 int tmp=sum(x2+1,y2+1)-sum(x1,y2+1)-sum(x2+1,y1)+sum(x1,y1); 86 printf("%d\n",tmp); 87 } 88 } 89 } 90 return 0; 91 }