POJ 1195 Mobile phones (二维树状数组)
题目大意:
对一个矩阵上的某个值进行改动。然后求出子矩阵的和。
思路分析:
这题discuss 上说二维线段树过不了。
所以二维树状数组搞。
理解树状数组的意义就是 1 - n 上全部的和。
然后两重循环。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define maxn 1040 #define lowbit(x) (x&(-x)) using namespace std; int C[maxn][maxn]; int n; void add(int x,int y,int a) { for(int i=x;i<=n;i+=lowbit(i)) { for(int j=y;j<=n;j+=lowbit(j)) { C[i][j]+=a; } } //printf("out %d %d\n",x,y); } int Sum(int L,int B,int R,int T) { int res=0; for(; R>0 ; R -=lowbit(R)) { int p=0,q=0; for(int i=T ; i>0 ; i-=lowbit(i))p+=C[R][i]; for(int i=B-1; i>0 ; i-=lowbit(i))q+=C[R][i]; res+=p-q; } int ret=0; for(L=L-1; L>0 ;L-=lowbit(L)) { int p=0,q=0; for(int i=T; i>0 ;i-=lowbit(i))p+=C[L][i]; for(int i=B-1; i>0 ;i-=lowbit(i))q+=C[L][i]; ret+=p-q; } //printf("%d %d\n",res,ret); return res-ret; } void debug() { for(int i=1;i<=4;i++) { for(int j=1;j<=4;j++) { printf("%d ",C[i][j]); } puts(""); } } int main() { int op; while(scanf("%d",&op)!=EOF) { if(op==0) { scanf("%d",&n); memset(C,0,sizeof C); } else if(op==1) { int x,y; int a; scanf("%d%d%d",&x,&y,&a); x++,y++; add(x,y,a); } else if(op==2) { int L,B,R,T; scanf("%d%d%d%d",&L,&B,&R,&T); L++,B++,R++,T++; printf("%d\n",Sum(L,B,R,T)); } else break; //debug(); } return 0; }