POJ 1195 Mobile phones(二维BIT)

Description
给出一个n*n的矩阵,初始化为均为0,还有关于这个矩阵的几种操作,操作如下:
命令1:(X Y A)对位于坐标(X Y)的值加A;
命令2:(L B R T)求出位于L<=x<=R,B<=y<=T的值的和;
命令3:退出不做任何操作。
Input
每行首先有一个整数res代表操作
res=0时输入矩阵行(列)数n(n<=1024)
res=1时输入X,Y,A,表示在(X,Y)的值加A(-32768 <= A <= 32767 )
res=2时输入L,B,R,T,表示查询位于L<=x<=R,B<=y<=T的值的和
res=3时结束输入
其中,每个坐标点的值范围为0<=V<=32767,操作数3<=U<=60002
注意:矩阵下标从0开始
Output
对于每个操作2,输出位于L<=x<=R,B<=y<=T的值的和
Sample Input
0 4
1 1 2 3
2 0 0 2 2
1 1 1 2
1 1 2 -1
2 1 1 2 3
3
Sample Output
3
4
Solution
二维树状数组,典型的动态操作题目
查询子矩阵(x,y,xx,yy)的元素和:sum(xx, yy)-sum(x-1, yy)-sum(xx, y-1)+sum(x-1,y-1)
Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define maxn 1030
int ins,m,n;
int bit[maxn][maxn];
int sum(int i,int j)//计算坐标(i,j)左上方子矩阵的部分和 
{
    int t,s=0;
    while(i>0)
    {
        t=j;
        while(t>0)
        {
            s+=bit[i][t];
            t-=t&-t;
        }
        i-=i&-i;
    }
    return s;
}
void add(int i,int j,int x)//将坐标点(i,j)值加x 
{
    int t;
    while(i<=n)
    {
        t=j;
        while(t<=n)
        {
            bit[i][t]+=x;
            t+=t&-t;
        }
        i+=i&-i;
    }
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(bit,0,sizeof(bit));//初始化 
        while(scanf("%d",&ins)&&ins!=3)
        {
            if(ins==1)//更新单点值 
            {
                int x,y,w;
                scanf("%d%d%d",&x,&y,&w);
                x++;y++;
                add(x,y,w);             
            }
            else if(ins==2)//查询子矩阵和 
            {
                int x,y,xx,yy;
                scanf("%d%d%d%d",&x,&y,&xx,&yy);
                x++;y++;xx++;yy++;//输入的下标从0开始,故要改成从1开始 
                printf("%d\n",sum(xx,yy)-sum(x-1,yy)-sum(xx,y-1)+sum(x-1,y-1));
            }
        }
    }
    return 0;
}

你可能感兴趣的:(POJ 1195 Mobile phones(二维BIT))