假设您有一个空数组:
0 0 0 0 0 0 0 0 0 0 (array)
0 0 0 0 0 0 0 0 0 0 (cumulative sums)
您想将范围更新为+5到[3..7]:
0 0 0 5 5 5 5 5 0 0 (array)
0 0 0 5 10 15 20 25 25 25 (desired cumulative sums)
如何使用2个二值索引树存储所需的累积总和?
诀窍是使用两个二进制索引树BIT1和BIT2,它们的累加总和是根据它们的内容来计算的。在此示例中,这是我们在两棵树中存储的内容:
0 0 0 5 5 5 5 5 0 0 (BIT1)
0 0 0 10 10 10 10 10 -25 -25 (BIT2)
要查找sum[i]
,您可以计算出以下内容:
sum[i] = BIT1[i] * i - BIT2[i]
例如:
sum[2] = 0*2 - 0 = 0
sum[3] = 5*3 - 10 = 5
sum[4] = 5*4 - 10 = 10
...
sum[7] = 5*7 - 10 = 25
sum[8] = 0*8 - (-25) = 25
sum[9] = 0*9 - (-25) = 25
为了实现先前范围更新的期望BIT1和BIT2值,我们进行了3次范围更新:
我们需要将BIT1的范围更新为+5到索引3..7。
我们需要将BIT2的范围更新为+10到索引3..7。
我们需要将BIT2的范围更新为-25到索引8..9。
现在让我们再进行一次转换。实际上,我们没有存储上面显示的BIT1和BIT2的值,而是存储了它们的累加和。这使我们可以通过对累积总和进行4次更新来进行上述3次范围更新:
BIT1sum[3] += 5
BIT1sum[8] -= 5
BIT2sum[3] += 10
BIT2sum[8] -= 35
通常,将值v添加到range [i..j]的算法为:
BIT1sum[i] += v
BIT1sum[j+1] -= v
BIT2sum[i] += v * (i-1)
BIT2sum[j+1] -= v * j
其中+ =和-=语法仅表示用该索引处的正值或负值更新BIT累积和数据结构。请注意,在更新索引处的BIT累积总和时,它将隐式影响该索引右边的所有索引。例如:
0 0 0 0 0 0 0 0 0 0 (original)
BITsum[3] += 5
0 0 0 5 5 5 5 5 5 5 (after updating [3])
BITsum[8] -= 5
0 0 0 5 5 5 5 5 0 0 (after updating [8])
O(logn)
sum[i] = BIT1[i] * i - BIT2[i]
什么?似乎可行,但似乎太武断了……有什么见识可以使您对此有所了解?