POJ1195 Mobile phones(简单二维树状数组)
分析:二维树状数组基本应用。题中的二维数组是从0到S-1,我们读入数据的时候自动把格子坐标加上1,使得二维数组下标从1到S。
有两点需要注意:
1.如果给(x,y)格子加上一个负数,该格子最小不能为0,所以需要另外维护一个A[x][y]保存它当前的值。
2.sum(x,y)求出的结果是左上角为(1,1)右下角为(x,y)的矩阵的和。但是题目中要求左上角为(x1,y1)右下角为(x2,y2)的矩阵的和。这个值为:
sum(x2,y2)+sum(x1-1,y1-1)-sum(x2,y1-1)-sum(x1-1,y2)。
AC代码:579ms
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN= 1200; int a[MAXN][MAXN]; int c[MAXN][MAXN]; int lowbit(int x){ return x&(-x); } int sum(int i,int j) { int res=0; for(int x=i;x>0;x-=lowbit(x)) for(int y=j;y>0;y-=lowbit(y)) res += c[x][y]; return res; } void add(int i,int j,int v) { if(v+a[i][j]<0) { v=-abs(a[i][j]); } a[i][j] +=v; for(int x=i;x<MAXN;x+=lowbit(x)) for(int y=j;y<MAXN;y+=lowbit(y)) c[x][y] +=v; } int main() { int op,n; scanf("%d%d",&op,&n); memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); while(scanf("%d",&op)==1) { if(op==2) { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++;y1++;x2++;y2++;//注意 printf("%d\n", sum(x2,y2)+sum(x1-1,y1-1)-sum(x2,y1-1)-sum(x1-1,y2) ); } else if(op==1) { int x,y,v; scanf("%d%d%d",&x,&y,&v); x++;y++;//注意 add(x,y,v); } else break; } return 0; }