[学习笔记]树状数组
普通的树状数组想必大家应该很熟悉了.今天来简单地谈谈树状数组的区修区查.
一维树状数组
\(\varDelta_x\)表示区间\([x,n]\)的共同增量.
利用的差分的思想,对于区间\([l,r]\),每次修改\(\varDelta_l,\varDelta_{r+1}\)即可.
这就解决了区间加的问题.
考虑求和,\(a_x=a'_i+\sum_{i=1}^{x}\varDelta_i\)
\(\begin{split}s_x&=\sum_{i=1}^{x}a_i\\&=\sum_{i=1}^{x}a'_i+\sum_{i=1}^{x}(x-i+1)\varDelta_i\\&=\sum_{i=1}^{x}a'_i+\sum_{i=1}^{x}\varDelta_i\times(x+1)-\sum_{i=1}^{x}\varDelta_i\times{i}\end{split}\)
所以只需维护\(\varDelta_i,\varDelta_i\times{i}\)的前缀和即可.
struct BIT{
int s[N];
inline int lowbit(int x){
return x&(-x);
}
lnline void add(int x,int k){
if(!i) return;
for(int i=x;i<=n;i+=lowbit(i))
s[i]+=k;
}
lnline int ask(int x){
int ret=0;
for(int i=x;i;i-=lowbit(i))
ret+=s[i];
return ret;
}
};
struct bit{
BIT a,ai;int s[N];
inline void init(){
for(int i=1;i<=n;++i) s[i]=read();
for(int i=1;i<=n;++i) s[i]+=s[i-1];
}
inline void add(int l,int r,int k){
a.add(l,k);a.add(r+1,-k);
ai.add(l,l*k);ai.add(r+1,-(r+1)*k);
}
inline void ask(int l,int r){
return (s[r]+a.ask(r)*(r+1)-ai.ask(r))-(s[l-1]+a.ask(l-1)*l-ai.ask(l-1));
}
}s;
二维树状数组
把刚刚的思想扩展到二维.
\(\varDelta_{x,y}\)表示区间\((x,y)-(n,n)\)的共同增量.
利用的差分的思想,对于区间\((x_l,y_l)-(x_r,y_r)\),每次修改\(\varDelta_{x_l,y_l},\varDelta_{x_r,y_l},\varDelta_{x_l,y_r},\varDelta_{x_r,y_r}\)即可.
考虑求和,\(a_{x,y}=a'_{x,y}+\sum_{i=1}^{x}\sum_{j=1}^{y}\varDelta_{i,j}\)
\(\begin{split}s_{x,y}&=\sum_{i=1}^{x}\sum_{j=1}^{y}a_{i,j}\\&=\sum_{i=1}^{x}\sum_{j=1}^{y}a'_{i,j}+\sum_{i=1}^{x}\sum_{j=1}^{y}(x-i+1)(y-j+1)\varDelta_{i,j}\\&=\sum_{i=1}^{x}\sum_{j=1}^{y}a'_{i,j}+\sum_{i=1}^{x}\sum_{j=1}^{y}(x+1)(y+1)\varDelta_{i,j}\\&\;\;\;-\sum_{i=1}^{x}\sum_{j=1}^{y}(x+1)\times{j}\times\varDelta_{i,j}-\sum_{i=1}^{x}\sum_{j=1}^{y}(y+1)\times{i}\times\varDelta_{i,j}\\&\;\;\;+\sum_{i=1}^{x}\sum_{j=1}^{y}i\times{j}\times\varDelta_{i,j}\end{split}\)
所以只需维护\(\varDelta_{i,j},\varDelta_{i,j}\times{j},\varDelta_{i,j}\times{i},\varDelta_{i,j}\times{i}\times{j}\)的前缀和即可.
struct BIT{
int s[N][N];
inline int lowbit(int x){
return x&(-x);
}
inline void add(int x,int y,int k){
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
s[i][j]+=k;
}
inline int ask(int x,int y){
int ret=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
ret+=s[i][j];
return ret;
}
};
struct bit{
BIT a,ai,aj,aij;int s[N][N];
void init(){
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
s[i][j]=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
s[i][j]+=s[i][j-1];
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
s[i][j]+=s[i-1][j];
}
inline void Add(int x,int y,int k){
a.add(x,y,k);ai.add(x,y,-x*k);aj.add(x,y,-y*k);aij.add(x,y,x*y*k);
}
inline void add(int a,int b,int c,int d,int k){
Add(a,b,k);Add(c+1,b,-k);Add(a,d+1,-k);Add(c+1,d+1,k);
}
inline int Ask(int x,int y){
return s[x][y]+a.ask(x,y)*(x+1)*(y+1)+ai.ask(x,y)*(y+1)+aj.ask(x,y)*(x+1)+aij.ask(x,y);
}
inline int ask(int a,int b,int c,int d){
return Ask(c,d)-Ask(a-1,d)-Ask(c,b-1)+Ask(a-1,b-1);
}
}s;
2017-04-09 00:07:20