動機
當初看binary index tree看了很久,要記錄一下
binary index tree
tree的樣子
build
因為是prefix sum所以如果從底部往上建,就是把目前建好的node往上一層送
像是1~1就是1~2的前半部,1~4就是1~2與3~3
那要怎麼決定要往那一個地方送? 這就是特別的地方了,往n+lowbit(n)
lowbit定義成離左邊(最低位)最近的第一個1,像
- lowbit(1) => 1
- lowbit(2) => 2
- lowbit(3) => 1
因為每次往上都是遞增一個lowbit(n),所以很像list
def __init__(self,arr):
self.n = len(arr)
self.bit = [0] * (1+self.n)
for (i,n) in enumerate(arr):
i += 1 # bit start from 1
self.bit[i] += n
nextI = i + (i&(-i)) # lowbit(i)
if nextI <= self.n:
self.bit[nextI] += self.bit[i]
update
剛剛的build是從底往上,update也是所以兩個很像
def update(self,i,diff):
while i <= self.n:
self.bit[i] += diff
i += (i&(-i))
query
build與update都是往上加lowbit(n),query可以類推成扣lowbit(n)? 對
def query(self,n): # [1..n]
ret = 0
while n > 0:
ret += self.bit[n]
n -= (n&(-n))
return ret
為什麼是lowbit?
從lowbit去看每個區間會發現lowbit(n)到左邊(最低位)的距離就是會有幾個區間要加,像
- lowbit(1) => 0 (就是自己)
- lowbit(2) => 1 (1~1與自己)
- lowbit(4) => 2 (1~2與3~3與自己)
還有lowbit(n)到左邊(最低位)的range,如果有1可以看成有幾個node,像
- 1~5 => 101,1~4與5~5
- 1~7 => 111,1~4與5~6與7~7
從這裡也可以看出來,為什麼bit的query是1~n,因為是透過binary去看有幾個1去加總
所以,bit就是利用binary來表示有幾個區間的prefix sum tree