大家都知道普通的树状数组的实现,
大致是这样的:
节点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
有了这两个公式,能够很方便地得到一个节点地左右儿子,
便可以类似线段树地方式实现很多功能。
未完待续。。。