一维树状数组
长度为 n n n的序列: a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,⋯,an
一阶差分与前缀和
一阶差分数组: d i = a i − a i − 1 ( a 0 = 0 ) d_i=a_i-a_{i-1}\qquad(a_0=0) di=ai−ai−1(a0=0)
考虑序列 a a a第 m m m项:
a m = ∑ i = 1 m d i a_m=\sum\limits_{i=1}^m d_i am=i=1∑mdi
考虑序列 a a a前 m m m项和:
∑ i = 1 m a i = ∑ i = 1 m ∑ j = 1 i d j = ∑ i = 1 m ( m + 1 − i ) ⋅ d i = ( m + 1 ) ∑ i = 1 m d i − ∑ i = 1 m i ⋅ d i \sum\limits_{i=1}^ma_i=\sum\limits_{i=1}^m\sum\limits_{j=1}^id_j=\sum\limits_{i=1}^m(m+1-i)\cdotp d_i=(m+1)\sum\limits\limits_{i=1}^md_i-\sum\limits_{i=1}^mi\cdotp d_i i=1∑mai=i=1∑mj=1∑idj=i=1∑m(m+1−i)⋅di=(m+1)i=1∑mdi−i=1∑mi⋅di
//区间加常数
for(int i=l;i<=r;++i)
a[i]+=v;
//查询区间和
for(int i=l;i<=r;++i)
sum+=a[i];
return sum;
树状数组优化上面的代码, 复杂度: O ( n log n ) O(n\log n) O(nlogn)
struct BinaryIndexTree
{
static const int __=1e5+5;
typedef ll type;
int n;type a[2][__];
void add(int x,type v)
{
for(int i=x;i<=n;i+=i&-i)
{
a[0][i]+=v;
a[1][i]+=x*v;
}
}
void add(int l,int r,type v)
{
if(l>r)return;
add(l,v),add(r+1,-v);
}
type sum(int x)
{
type b[2]={0};
for(int i=x;i;i-=i&-i)
{
b[0]+=a[0][i];
b[1]+=a[1][i];
}
return (x+1)*b[0]-b[1];
}
type sum(int l,int r)
{
if(l>r)return 0;
return sum(r)-sum(l-1);
}
}B;
二阶差分与前缀和
二阶差分数组: e i = d i − d i − 1 = a i − 2 ⋅ a i − 1 + a i − 2 ( a − 1 = a 0 = 0 ) e_i=d_i-d_{i-1}=a_i-2\cdotp a_{i-1}+a_{i-2}\qquad(a_{-1}=a_0=0) ei=di−di−1=ai−2⋅ai−1+ai−2(a−1=a0=0)
考虑序列 a a a第 m m m项:
a m = ∑ i = 1 m d i = ∑ i = 1 m ∑ j = 1 i e j = ( m + 1 ) ∑ i = 1 m e i − ∑ i = 1 m i ⋅ e i a_m=\sum\limits_{i=1}^m d_i=\sum\limits_{i=1}^m\sum\limits_{j=1}^ie_j=(m+1)\sum\limits\limits_{i=1}^me_i-\sum\limits_{i=1}^mi\cdotp e_i am=i=1∑mdi=i=1∑mj=1∑iej=(m+1)i=1∑mei−i=1∑mi⋅ei
考虑序列 a a a前 m m m项和:
∑ i = 1 m a i = ∑ i = 1 m ( ( i + 1 ) ∑ j = 1 i e j − ∑ j = 1 i j ⋅ e j ) = ( ∑ i = 1 m e i ∑ j = i + 1 m + 1 j ) − ( ∑ i = 1 m e i ⋅ ( ( m + 1 − i ) ⋅ i ) ) = ( ∑ i = 1 m e i ⋅ ( m + 2 + i ) ⋅ ( m + 1 − i ) 2 ) − ( ∑ i = 1 m e i ⋅ ( ( m + 1 − i ) ⋅ i ) ) = ∑ i = 1 m e i ⋅ ( m + 2 − i ) ⋅ ( m + 1 − i ) 2 = ∑ i = 1 m e i ⋅ ( m 2 + 3 m + 2 ) − ( 2 m + 3 ) ⋅ i + i 2 2 = ( m + 1 ) ( m + 2 ) 2 ∑ i = 1 m e i − 2 m + 3 2 ∑ i = 1 m i ⋅ e i + 1 2 ∑ i = 1 m i 2 ⋅ e i \begin{aligned} \sum\limits_{i=1}^ma_i&=\sum\limits_{i=1}^m\Big((i+1)\sum\limits\limits_{j=1}^ie_j-\sum\limits_{j=1}^ij\cdotp e_j\Big)\\ &=\Big(\sum\limits_{i=1}^me_i\sum\limits_{j=i+1}^{m+1}j\Big)-\Big(\sum\limits_{i=1}^me_i\cdot\big((m+1-i)\cdotp i\big)\Big)\\ &=\Big(\sum\limits_{i=1}^me_i\cdot\frac{(m+2+i)\cdotp(m+1-i)}{2}\Big)-\Big(\sum\limits_{i=1}^me_i\cdot\big((m+1-i)\cdotp i\big)\Big)\\ &=\sum\limits_{i=1}^me_i\cdot\frac{(m+2-i)\cdotp(m+1-i)}{2}\\ &=\sum\limits_{i=1}^me_i\cdot\frac{(m^2+3m+2)-(2m+3)\cdotp i+i^2}{2}\\ &=\frac{(m+1)(m+2)}{2}\sum\limits_{i=1}^me_i-\frac{2m+3}{2}\sum\limits_{i=1}^mi\cdotp e_i+\frac{1}{2}\sum\limits_{i=1}^mi^2\cdotp e_i \end{aligned} i=1∑mai=i=1∑m((i+1)j=1∑iej−j=1∑ij⋅ej)=(i=1∑meij=i+1∑m+1j)−(i=1∑mei⋅((m+1−i)⋅i))=(i=1∑mei⋅2(m+2+i)⋅(m+1−i))−(i=1∑mei⋅((m+1−i)⋅i))=i=1∑mei⋅2(m+2−i)⋅(m+1−i)=i=1∑mei⋅2(m2+3m+2)−(2m+3)⋅i+i2=2(m+1)(m+2)i=1∑mei−22m+3i=1∑mi⋅ei+21i=1∑mi2⋅ei
//区间加一次函数
for(int i=l;i<=r;++i)
a[i]+=(i-l)*k+b;
//查询区间和
for(int i=l;i<=r;++i)
sum+=a[i];
return sum;
树状数组优化以上代码, 复杂度: O ( n log n ) O(n\log n) O(nlogn)
struct BinaryIndexTree
{
static const int __=1e5+5;
typedef ll type;
int n;type a[3][__];
void add(int x,type v)
{
for(int i=x;i<=n;i+=i&-i)
{
a[0][i]+=v;
a[1][i]+=x*v;
a[2][i]+=x*x*v;
}
}
//a[i]+=b+k*(i-l)
void add(int l,int r,type k,type b)
{
if(l>r)return;
add(l,b);
add(l+1,k-b);
add(r+1,-b-(r-l+1)*k);
add(r+2,b+(r-l)*k);
}
type sum(int x)
{
type b[3]={0};
for(int i=x;i;i-=i&-i)
{
b[0]+=a[0][i];
b[1]+=a[1][i];
b[2]+=a[2][i];
}
return ((x+1)*(x+2)*b[0]-(2*x+3)*b[1]+b[2])/2;
}
type sum(int l,int r)
{
if(l>r)return 0;
return sum(r)-sum(l-1);
}
}B;
k k k阶差分与前缀和
不难看出: 在维护原数组 a i a_i ai的 k k k阶差分数组 b i b_i bi时, a i a_i ai的前 m m m项和都是如下几个相同形式的部分求和
∑ f ( m ) ⋅ ∑ i = 1 m i c ⋅ b i ( f ( x ) \sum f(m)\cdotp\sum\limits_{i=1}^m i^c\cdotp b_i\qquad\big(f(x) ∑f(m)⋅i=1∑mic⋅bi(f(x)是关于 x x x的多项式 ) \big) )
考虑一个部分的前 m m m项和:
∑ i = 1 m f ( i ) ∑ j = 1 i j c ⋅ b j = ∑ i = 1 m i c ⋅ b i ∑ j = i m f ( j ) = ∑ i = 1 m i c ⋅ b i ⋅ ( ∑ j = 1 m f ( j ) − ∑ j = 1 i − 1 f ( j ) ) = ∑ i = 1 m i c ⋅ b i ⋅ ( g ( m ) − g ( i − 1 ) ) ( g ( n ) = ∑ i = 1 n f ( i ) ) \begin{aligned} \sum\limits_{i=1}^mf(i)\sum\limits_{j=1}^i j^c\cdotp b_j&=\sum\limits_{i=1}^mi^c\cdotp b_i\sum\limits_{j=i}^m f(j)=\sum\limits_{i=1}^mi^c\cdot b_i\cdotp\Big(\sum\limits_{j=1}^m f(j)-\sum\limits_{j=1}^{i-1} f(j)\Big)\\ &=\sum\limits_{i=1}^mi^c\cdot b_i\cdotp\big(g(m)-g(i-1)\big)\qquad\Big(g(n)=\sum\limits_{i=1}^n f(i)\Big) \end{aligned} i=1∑mf(i)j=1∑ijc⋅bj=i=1∑mic⋅bij=i∑mf(j)=i=1∑mic⋅bi⋅(j=1∑mf(j)−j=1∑i−1f(j))=i=1∑mic⋅bi⋅(g(m)−g(i−1))(g(n)=i=1∑nf(i))
运用上述方法不难求得三阶差分数组 f i f_i fi与前缀和的关系
∑ i = 1 m a i = ( m + 1 ) ( m + 2 ) ( m + 3 ) 6 ∑ i = 1 m f i − 3 m 2 + 12 m + 11 6 ∑ i = 1 m i ⋅ f i + m + 2 2 ∑ i = 1 m i 2 ⋅ f i − 1 6 ∑ i = 1 m i 3 ⋅ f i \sum\limits_{i=1}^ma_i=\frac{(m+1)(m+2)(m+3)}{6}\sum\limits_{i=1}^m f_i-\frac{3m^2+12m+11}{6}\sum\limits_{i=1}^m i\cdotp f_i+\frac{m+2}{2}\sum\limits_{i=1}^m i^2\cdotp f_i-\frac{1}{6}\sum\limits_{i=1}^m i^3\cdotp f_i i=1∑mai=6(m+1)(m+2)(m+3)i=1∑mfi−63m2+12m+11i=1∑mi⋅fi+2m+2i=1∑mi2⋅fi−61i=1∑mi3⋅fi
//区间加二次函数
for(int i=l;i<=r;++i)
a[i]+=(i-l)*(i-l)*x+(i-l)*y+z;
//查询区间和
for(int i=l;i<=r;++i)
sum+=a[i];
return sum;
树状数组优化以上代码, 复杂度: O ( n log n ) O(n\log n) O(nlogn)
struct BinaryIndexTree
{
static const int __=1e5+5;
typedef ll type;
int n;type a[4][__];
void add(int x,type v)
{
for(int i=x;i<=n;i+=i&-i)
{
a[0][i]+=v;
a[1][i]+=x*v;
a[2][i]+=x*x*v;
a[3][i]+=x*x*x*v;
}
}
//a[i]+=x*(i-l)*(i-l)+y*(i-l)+z;
void add(int l,int r,type x,type y,type z)
{
if(l>r)return;
add(l,z);
add(l+1,x+y-2*z);
add(l+2,x-y+z);
type p=r-l+1,q=r-l;
add(r+1,-p*p*x-p*y-z);
add(r+2,(p*p+q*q-2)*x+(p+q)*y+2*z);
add(r+3,-q*q*x-q*y-z);
}
type sum(int x)
{
type b[4]={0};
for(int i=x;i;i-=i&-i)
{
b[0]+=a[0][i];
b[1]+=a[1][i];
b[2]+=a[2][i];
b[3]+=a[3][i];
}
return ((x+1)*(x+2)*(x+3)*b[0]-(3*x*x+12*x+11)*b[1]+(3*x+6)*b[2]-b[3])/6;
}
type sum(int l,int r)
{
if(l>r)return 0;
return sum(r)-sum(l-1);
}
}B;