解題思路
二維樹狀數組。
對於修改操作單開一個矩陣,修改時利用差分思想,這樣每個點 的前綴和表示這個點修改了多少。
對於一個查詢 ,單獨考慮從 到 的每一個點,一個點 會被算進從 到 所有點的前綴和裏,所以 對本次查詢的貢獻爲 。
拆開變成: ,然後分別維護四個樹狀數組,查詢時加到一起。
代碼:
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n,m;
struct ldx{
int a[2050][2050];
void add(int x,int y,int num){
for(int i=x;i<=n;i+=i&(-i))
for(int j=y;j<=m;j+=j&(-j))
a[i][j]+=num;
}
int ch(int x,int y){
int sum=0;
for(int i=x;i>0;i-=i&(-i))
for(int j=y;j>0;j-=j&(-j))
sum+=a[i][j];
return sum;
}
}T1,T2,T3,T4;
inline void tj(int x,int y,int num){
T1.add(x,y,num);
T2.add(x,y,num*x);
T3.add(x,y,num*y);
T4.add(x,y,num*x*y);
}
inline int solve(int x,int y){
return (x+1)*(y+1)*T1.ch(x,y)-(y+1)*T2.ch(x,y)-(x+1)*T3.ch(x,y)+T4.ch(x,y);
}
int main(){
int ai,bi,ci,di,ei;
char opt[5];
scanf("%s%d%d",opt,&n,&m);
while(~scanf("%s",opt)){
if(opt[0]=='L'){
scanf("%d%d%d%d%d",&ai,&bi,&ci,&di,&ei);
tj(ai,bi,ei);tj(ci+1,di+1,ei);
tj(ci+1,bi,-ei);tj(ai,di+1,-ei);
}
else {
scanf("%d%d%d%d",&ai,&bi,&ci,&di);
int ans=solve(ci,di)+solve(ai-1,bi-1)-solve(ci,bi-1)-solve(ai-1,di);
printf("%d",ans);
}
}
return 0;
}