树状数组Q

树状数组

定义 l o w b i t ( i ) = 2 x lowbit(i)=2^x lowbit(i)=2x,其中 x x x为满足 2 x & i = 2 x 2^x\& i=2^x 2x&i=2x的最小的自然数,即 i i i二进制表示的最低位。
定义 ⊕ \oplus 为满足结合律的某种运算,这里暂时将 ⊕ \oplus 看作加法。
定义 b i t [ x ] = a x − l o w b i t ( x ) + 1 ⊕ . . . ⊕ a x − 1 ⊕ a x = ∑ i = x − l o w b i t ( x ) + 1 x a i bit[x]=a_{x-lowbit(x)+1}\oplus...\oplus a_{x-1}\oplus a_x=\sum\limits_{i=x-lowbit(x)+1}^xa_i bit[x]=axlowbit(x)+1...ax1ax=i=xlowbit(x)+1xai
现在我们要求 s u m r = ∑ i = 1 r a i sum_r=\sum_{i=1}^r a_i sumr=i=1rai,我们有 s u m r = ∑ i = 1 r a i = b i t [ r ] + a r − l o w b i t ( r ) + . . . + a 2 + a 1 = b i t [ r ] + s u m r − l o w b i t ( r ) sum_r=\sum_{i=1}^r a_i=bit[r]+a_{r-lowbit(r)}+...+a_2+a_1\\=bit[r]+sum_{r-lowbit(r)} sumr=i=1rai=bit[r]+arlowbit(r)+...+a2+a1=bit[r]+sumrlowbit(r)
特别的有 s u m 0 = 0 sum_0=0 sum0=0
于是有了树状数组的递归计算:

int lowbit(int x){return x&-x;}
int query(int x)
{
	int ans=0;
	while(x)
	{
		ans+=bit[x];
		x-=lowbit(x);
	}
	return ans;
}

这里 x & − x x\&-x x&x就是 l o w b i t ( x ) lowbit(x) lowbit(x),可以用组成原理的知识推导。
树状数组还需要解决的问题是添加操作:
如果将 a x a_x ax加上 v v v,那么数组该如何变化?
对于整数 i i i b i t [ i ] bit[i] bit[i]维护的是区间 [ i − l o w b i t ( i ) + 1 , i ] [i-lowbit(i)+1,i] [ilowbit(i)+1,i]的和,那么对于所有满足 i − l o w b i t ( i ) + 1 ≤ x ≤ i i-lowbit(i)+1\le x\le i ilowbit(i)+1xi i i i要更新 b i t [ i ] = b i t [ i ] + v bit[i]=bit[i]+v bit[i]=bit[i]+v,称满足这样的条件的 i i i需更新的数。
其次,这样的 i i i是有无限个的,我们只需要取数组的上限 n n n,取所有 i ≤ n i\le n in i i i
首先,最小的满足这样的 i i i x x x本身。
其次,若 y y y满足 x ∈ [ y − l o w b i t ( y ) + 1 , y ] x\in[y-lowbit(y)+1,y] x[ylowbit(y)+1,y],我们证明 z = y + l o w b i t ( y ) z=y+lowbit(y) z=y+lowbit(y)是大于 y y y最小的需更新的数。
证:
0 < t < l o w b i t ( y ) 0<t<lowbit(y) 0<t<lowbit(y),则 l o w b i t ( y + t ) ≤ t lowbit(y+t)\le t lowbit(y+t)t(观察二进制易证),从而 y + t − l o w b i t ( y + t ) + 1 ≥ y + t − t + 1 = y + 1 > y y+t-lowbit(y+t)+1\ge y+t-t+1=y+1> y y+tlowbit(y+t)+1y+tt+1=y+1>y
故对于任意 y < i < y + l o w b i t ( y ) = z y<i<y+lowbit(y)=z y<i<y+lowbit(y)=z i i i,都不是需更新的数。
下面再证 z z z是需更新的数,观察二进制易发现 l o w b i t ( z ) ≥ l o w b i t ( y ) ∗ 2 lowbit(z)\ge lowbit(y)*2 lowbit(z)lowbit(y)2,则 z − l o w b i t ( z ) ≤ ( y + l o w b i t ( y ) ) − 2 ∗ l o w b i t ( y ) = y − l o w b i t ( y ) z-lowbit(z)\le (y+lowbit(y))-2*lowbit(y)=y-lowbit(y) zlowbit(z)(y+lowbit(y))2lowbit(y)=ylowbit(y),由 z = y + l o w b i t ( y ) > y z=y+lowbit(y)>y z=y+lowbit(y)>y,故 x ∈ [ y − l o w b i t ( y ) , y ] ∈ [ z − l o w b i t ( z ) , z ] x\in [y-lowbit(y),y]\in [z-lowbit(z),z] x[ylowbit(y),y][zlowbit(z),z]
从而有了树状数组的添加过程:

int lowbit(int x){return x&-x;}
void add(int x,int v)
{
	while(x<=n)
	{
		bit[x]+=v;
		x+=lowbit(x);
	}
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值