大家都知道普通的树状数组的实现,
大致是这样的:
节点k,统计的叶子范围为:
[k−lowbit(k)+1,k]
而每一个节点都只记录左儿子的信息,
我们能够查询的也就只是
[1,n]
的信息。
通常使用树状数组维护前缀和,但有时也能用来做一些看似只有线段树才能实现的功能。
区间更新
我们用前缀和维护每个位置的增加的值。
记
S[i]
表示
[i,n]
位置上的数都增加
S[i]
的值。
那么如果对
[l,r]
增加d,就
S[l]+d,S[r+1]−d
。
求和的话,设原数组为
A
,那么对
答案就是:
Ans=∑i=lr(A[i]+(r−i+1)∗S[i])=∑i=lrA[i]+∑i=lr(r∗S[i]−i∗S[i]+S[i])=∑i=lrA[i]+(r+1)∑i=lrS[i]−∑i=lri∗S[i]
而现在上面的 ∑ri=lA[i],∑ri=lS[i],∑ri=li∗S[i] 都可以维护。
后面两个由于都只有单点的修改,即可使用树状数组。( i∗S[i] 将要增加的值乘以i就行了)
下面再给出两个公式:
i节点的左儿子编号为: i−lowbit(i)2
i节点的右儿子编号为: i+lowbit(i)2
有了这两个公式,能够很方便地得到一个节点地左右儿子,
便可以类似线段树地方式实现很多功能。
未完待续。。。