上次我们聊到了二维树状数组的 单点加 区间查.
那么我们yy一下区间加 单点查也不难.
我们就让树状数组维护差分数组, 只不过是变成了二维差分, 都差不多的.
我们可以仿照一维的 改写成这样
int c[N][N],n,m;
void add(int x,int y,int s){
for(int i=x;i<=n;i+=i&-i)
for(int j=y;j<=m;j+=j&-j)
c[i][j]+=s;
}
int query(int x,int y,int s=0){
for(int i=x;i;i-=i&-i)
for(int j=y;j;j-=i&-j)
s+=c[i][j];
}
void Add(int x1,int y1,int x2,int y2,int s){
add(x1,y1,s); add(x1,y2+1,-s); add(x2+1,y1,-s); add(x2+1,y2+1,s);
}
而其实二维树状数组也可以做到区间加, 区间查的.
而且据说线段树套线段树是没法维护的....
我们看一道本板子题: 上帝造题的七分钟
那怎么做呢? 我们还是仿照一维的推柿子.
不过今天我按照之前的方法推柿子感觉并不好推, 于是获取了一种新的推法.
由于我们维护的差分数组的前缀和才是单点的值, 也就是说我们计算(a_i)时, (c_1sim c_i)每个值都会被计算一次.
这样我们计算(sum_{i=1}^na_i)的时候,(c_1)应该会出现(n)次, (c_2)应该会出现(n-1)次, ... , (c_k)会出现(n-k+1)次, ... ,(c_n)会出现一次. 所以
这样我们用两个树状数组分别维护(c_i)的和和(c_i*i)的和即可.
而之前我们得出的结论也不是错的, 如果我们这么拆
就变成了维护(c_I)和(c_i*(i-1)), 最后结果应该是一样的, 具体用哪种看个人喜好吧... (似乎前面那种用起来比较舒服..)
情况扩展到了二维, 除了二维差分复杂了一(hen)些(duo)以外, 原理上是一样的.
我们依然用(c_{i,j})维护差分数组, 所以显然(sum_{i=1}^nsum_{j=1}^mc_{i,j}=a_{n,m})
然后仿照一维的, 把一个查询拆成四个, 对于每个查询,
这里面很显然每个(c_i,j)被使用的次数等于以((i,j))为左上角,((n,m))为右下角的矩形面积(不信你可以画个图试试), 也就是((n-i+1)*(m-j+1)), 所以
所以按照套路我们只需要开四个树状数组分别维护(c_{i,j},c_{i,j}*i,c_{i,j}*j,c_{i,j}*i*j)就行了..
不管是区间加还是区间查都巨繁琐qwq...
下面给出代码;
#include <cstdio>
inline int gn(int a=0,char c=0,int f=1){
for(;(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-') c=getchar(),f=-1;
for(;c>47&&c<58;c=getchar()) a=a*10+c-48;
return a*f;}
struct BIT{
int c[2050][2050],n,m;
void add(int x,int y,int s){
for(int i=x;i<=n;i+=i&-i)
for(int j=y;j<=m;j+=j&-j)
c[i][j]+=s;
}
int query(int x,int y,int s=0){
for(int i=x;i;i-=i&-i)
for(int j=y;j;j-=j&-j)
s+=c[i][j];
return s;
}
}a,b,c,d;
void Add(int x,int y,int s){
a.add(x,y,s); b.add(x,y,s*x); c.add(x,y,s*y); d.add(x,y,s*x*y);
}
int Query(int x,int y){
return a.query(x,y)*(x+1)*(y+1)-b.query(x,y)*(y+1)-c.query(x,y)*(x+1)+d.query(x,y);
}
int main(){
int n=gn(),m=gn(); char opt[4];
a.n=b.n=c.n=d.n=n; a.m=b.m=c.m=d.m=m;
while(~scanf("%s",opt)){
if(opt[0]=='L'){
int x1=gn(),y1=gn(),x2=gn(),y2=gn(),s=gn();
Add(x1,y1,s); Add(x1,y2+1,-s); Add(x2+1,y1,-s); Add(x2+1,y2+1,s);
}
else{
int x1=gn(),y1=gn(),x2=gn(),y2=gn();
printf("%d
",Query(x2,y2)-Query(x1-1,y2)-Query(x2,y1-1)+Query(x1-1,y1-1));
}
}
}