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