题目链接:
POJ 1195 Mobile phones
题意:
一个
S∗S
的矩阵,主要有种操作:
①:x,y,a将s[x][y]增加a,a可能为负值
②:L,B,R,T,查询L<=x<=R,B<=y<=T的所有元素和。
要求对每次查询输出结果。
分析:
题目中的原始下标是从0开始的,可以人为地每次都+1,这样就是从1开始的了。
用sum[i][j]来代替原来一维树状数组中的sum[i],那么每次查询相当于
∑sum[L,R] + ∑sum[L−1,R−1] - ∑sum[L−1,T] - ∑sum[R,B−1] ,
其中 sum[L,R]表示1<=i<=L,1<=j<=R的所有树状数组查找的有效sum[i][j] 和,其余类似。
//5076K 1032MS
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1100;
int com,n,x,y,num,left,below,right,top,ans;
int sum[maxn][maxn];
inline void update()
{
for(int i=x;i<=n;i+=(i&(-i))){
for(int j=y;j<=n;j+=(j&(-j))){
sum[i][j]+=num;
}
}
}
inline int solve(int MAX_X,int MAX_Y)
{
int res=0;
for(int i=MAX_X;i>0;i-=(i&(-i))){
for(int j=MAX_Y;j>0;j-=(j&(-j))){
res+=sum[i][j];
}
}
return res;
}
int main()
{
freopen("poj1195in.txt","r",stdin);
freopen("myout.txt","w",stdout);
while(~scanf("%d",&com)&&com!=3){
if(com==0){
scanf("%d",&n);
memset(sum,0,sizeof(sum));
}else if(com==1){
scanf("%d%d%d",&x,&y,&num);
x++;y++;
update();
}else {
scanf("%d%d%d%d",&left,&below,&right,&top);
left++;below++;right++;top++;
ans=solve(right,top)+solve(left-1,below-1)-solve(right,below-1)-solve(left-1,top);
printf("%d\n",ans);
}
}
return 0;
}