题目大意:有一个边长为S的正方形区域,每个小方块内都有一个基站和很多手机,一个小方块内的活跃手机数量不固定,因为手机可以移动到其他小方块内或者可以开机关机。根据给出的一系列变化情况,输出查询的指定区域内的活跃手机个数。区域内手机总共最多2^30个。小方块内手机个数0 <= V <= 32767。
输入:(四种情况,输入行数范围3 <= U <= 60002)
0 S(初始化S*S的每个小方块都为0,1 * 1 <= S * S <= 1024 * 1024)
1 X Y A(小方块(X,Y)内的活跃手机个数加A, -32768 <= A <= 32767,X,Y的范围是0~S-1)
2 L B R T(查询以(L,B)为左上角,(R,T)为右下角的区域内活跃手机的个数)
3(代表输入结束)
输出:对每个查询输出活跃手机个数(各占一行)
分析:二维树状数组。注意树状数组下标从1起,所以输入的坐标都要加1。二维和一维的同理更新和求和,只是稍作修改。
代码:转载自http://blog.csdn.net/lin375691011/article/details/21247409
#include <stdio.h>
#include <string.h>
int num[1050][1050],s;
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y,int val)
{
for(int i=x;i<=s;i+=lowbit(i))
{
for(int j=y;j<=s;j+=lowbit(j))
{
num[i][j]+=val;//num[][]相当于一维中的C[]数组,不过二维是在两个方向
}
}
}
int query(int x,int y)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
for(int j=y;j>0;j-=lowbit(j))
{
ans+=num[i][j];
}
}
return ans;
}
int main()
{
int t,q,x,y,sum,l,r,a;
scanf("%d%d",&t,&s);
memset(num,0,sizeof(num));
while(scanf("%d",&q),q<3)
{
if(q==1)
{
scanf("%d%d%d",&x,&y,&a);
x++;
y++;
add(x,y,a);
}
else if(q==2)
{
scanf("%d%d%d%d",&x,&y,&l,&r);
x++;
y++;
l++;
r++;
printf("%d\n",query(l,r)-query(l,y-1)-query(x-1,r)+query(x-1,y-1));
}
}
return 0;
}