POJ1195 Mobile phones(简单二维树状数组)

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;
}

你可能感兴趣的:(ACM)