Solution
二维树状数组
求
(x1,y1)
(
x
1
,
y
1
)
到
(x2,y2)
(
x
2
,
y
2
)
的和
sum=sum[x2][y2]−sum[x1−1][y2]−sum[x2][y1−1]+sum[x1−1][y1−1]
s
u
m
=
s
u
m
[
x
2
]
[
y
2
]
−
s
u
m
[
x
1
−
1
]
[
y
2
]
−
s
u
m
[
x
2
]
[
y
1
−
1
]
+
s
u
m
[
x
1
−
1
]
[
y
1
−
1
]
sum[x][y]=∑i=1x∑j=1y∑k=1i∑t=1ja[k][t]=∑i=1x∑j=1xa[i][j]∗(x−i+1)∗(y−j+1) s u m [ x ] [ y ] = ∑ i = 1 x ∑ j = 1 y ∑ k = 1 i ∑ t = 1 j a [ k ] [ t ] = ∑ i = 1 x ∑ j = 1 x a [ i ] [ j ] ∗ ( x − i + 1 ) ∗ ( y − j + 1 )
因此我们开四个二维树状数组就可以解决了
Code
#include <cstdio>
#define N 2050
int n,m,a,b,c,d,k;
char str[10];
struct BIT{
int tree[N][N];
void add(int x,int y,int z){
for(int i=x;i<=n;i+=i&(-i))
for(int j=y;j<=m;j+=j&(-j))
tree[i][j]+=z;
}
int query(int x,int y){
int ans=0;
for(int i=x;i;i-=i&-i)
for(int j=y;j;j-=j&-j)
ans+=tree[i][j];
return ans;
}
}A,Ai,Aj,Aij;
inline void add(int x,int y,int z){
A.add(x,y,z);
Ai.add(x,y,z*x);
Aj.add(x,y,z*y);
Aij.add(x,y,x*y*z);
}
inline int query(int x,int y){
return A.query(x,y)*(x*y+x+y+1)-Ai.query(x,y)*(y+1)-Aj.query(x,y)*(x+1)+Aij.query(x,y);
}
int main(){
scanf("%s%d%d",str,&n,&m);
while(scanf("%s%d%d%d%d",str,&a,&b,&c,&d)>0){
if(str[0]=='L'){
scanf("%d",&k);
add(a,b,k);
add(a,d+1,-k);
add(c+1,b,-k);
add(c+1,d+1,k);
}else printf("%d\n",query(c,d)-query(a-1,d)-query(c,b-1)+query(a-1,b-1));
}
return 0;
}