二维树状数组小记
做 LG1527,发现自己竟然还不会二维树状数组,赶紧恶补一下。
下面的内容是随手写的,原理不是很难
单点改,区间查
void update(int x,int y,int v){
for(int i=x;i<=n;i+=lowbit(i)){
for(int j=y;j<=m;j+=lowbit(j))
c[i][j]+=v;
}
}
int getsum(int x,int y,int v=0){
for(int i=x;i;i-=lowbit(i)){
for(int j=y;j;j-=lowbit(j))
v+=c[i][j];
}
return v;
}
最后答案统计
\[\sum_{i=a}^{c}\sum_{i=b}^{d}a_{i,j}=s_{c,d}-s_{c-1,d}-s_{c,d-1}+s_{c-1,d-1}
\]
区间改,单点查
定义差分数组 \(d_{i,j}\),每次修改操作 \(d_{a,b}\leftarrow +v,d_{c+1,b}\leftarrow-v,d_{a,d+1}\leftarrow-v,d_{c+1,d+1}\leftarrow+v\)
\[a_{x,y}=\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}
\]
转化为单点改,区间查
区间改,区间查询
\[\begin{align}
s_{x,y}&=\sum_{i=1}^{x}\sum_{j=1}^{y}a_{i,j}\\
&=\sum_{i=1}^{x}\sum_{j=1}^{y}\sum_{k=1}^{i}\sum_{l=1}^{j}d_{k,l}\\
&=\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times(x-i+1)(y-j+1)\\
&=(x+1)(y+1)\sum_{i=1}^{x}\sum_{j=1}^y d_{i,j}-(x+1)\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times j-(y+1)\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times i+\sum_{i=1}^{x}\sum_{j=1}^{y}d_{i,j}\times ij
\end{align}
\]
额外维护 \(d_{i,j}\times j,d_{i,j}\times i,d_{i,j}\times ij\) 的二维前缀和即可
LG4514 上帝造题的七分钟
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>ttfa;
const int N=2050;
inline int lowbit(int x){return x&-x;}
int n,m;
struct BIT_2di{
int c[N][N];
void update(int x,int y,int v){
for(int i=x;i<=n;i+=lowbit(i)){
for(int j=y;j<=m;j+=lowbit(j))
c[i][j]+=v;
}
}
int getsum(int x,int y,int v=0){
for(int i=x;i;i-=lowbit(i)){
for(int j=y;j;j-=lowbit(j))
v+=c[i][j];
}
return v;
}
}s,si,sj,sij;
void sij_update(int x,int y,int v){
s.update(x,y,v);
si.update(x,y,v*x);
sj.update(x,y,v*y);
sij.update(x,y,v*x*y);
}
int sij_getsum(int x,int y,int v=0){
v+=(x+1)*(y+1)*s.getsum(x,y);
v-=(x+1)*sj.getsum(x,y);
v-=(y+1)*si.getsum(x,y);
v+=sij.getsum(x,y);
return v;
}
int main(){
char opt[3];
scanf("%s%d%d",opt,&n,&m);
while(scanf("%s",opt)!=EOF){
int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);
if(opt[0]=='L'){
int v;scanf("%d",&v);
sij_update(a,b,v);
sij_update(c+1,b,-v);
sij_update(a,d+1,-v);
sij_update(c+1,d+1,v);
}else{
int v=0;
v+=sij_getsum(c,d);
v-=sij_getsum(a-1,d);
v-=sij_getsum(c,b-1);
v+=sij_getsum(a-1,b-1);
printf("%d\n",v);
}
}
return 0;
}
本文作者:BigSmall_En
本文链接:https://www.cnblogs.com/BigSmall-En/p/18605845
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步