Description
Input

Output
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
在S*S的数组中,某些区域的数值是时常变化的,编写程序计算出任意时刻,某一区域的数值和。
输入:
每行一个或多个数字,如果某一行的第一个数字是3时,结束操作;如果某一行的第一个数字是0,那么接下来只有一个数,是S;如果某一行的第一个数字是1时,接下来有三个数,分别是X,Y,A,表示在X,Y对应的点加上A(注意:X,Y可以为0);如果某一行的第一个数字是2时,接下来有四个数,分别是L,B,R,T,表示(L,B)与(R,T)所围区域的和。
解题思路:
利用二维树状数组求解,详细介绍请仔细查看代码及注释。
代码如下:
#include <stdio.h>
#include <string.h>
int S,a[1025][1025];
int lowbit(int x)
{
return x&(-x);
}
//更新二维树状数组,对(x,y)所在元素加num
void updata(int x,int y,int num)
{
int i,j;
for(i=x;i<=S;i+=lowbit(i))
{
for(j=y;j<=S;j+=lowbit(j))
{
a[i][j]+=num;
}
}
}
//求和((1,1)到(x,y)区域的所有元素的和)
int SUM(int x,int y)
{
int i,j,sum=0;
for(i=x;i>0;i-=lowbit(i))
{
for(j=y;j>0;j-=lowbit(j))
{
sum+=a[i][j];
}
}
return sum;
}
int main()
{
int t;
while(scanf("%d",&t)&&t!=3)
{
if(t==0)
{
scanf("%d",&S);
memset(a,0,sizeof(a));
}
if(t==1)
{
int X,Y,A;
scanf("%d%d%d",&X,&Y,&A);
updata(X+1,Y+1,A);
}
if(t==2)
{
int L,B,R,T;
scanf("%d%d%d%d",&L,&B,&R,&T);
printf("%d\n",SUM(L,B)+SUM(R+1,T+1)-SUM(L,T+1)-SUM(R+1,B));
}
}
return 0;
}
F - Mobile phones,布布扣,bubuko.com
原文地址:http://blog.csdn.net/yanghuaqings/article/details/38333481