Binary Indexed Tree
Ruby@NTUIM
Ruby@NTUIM
實際應用
運作方式
運作原理
程式實作
二元索引樹
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
二元索引樹 > 實際應用
前綴和 Prefix Sum
7 | 5 | 8 | 3 | -4 | 6 | 9 | 2 |
---|
Naive
Ruby@NTUIM
二元索引樹 > 實際應用
前綴和 Prefix Sum
7 | 5 | 8 | 3 | -4 | 6 | 9 | 2 |
---|
7
12
20
23
19
25
34
36
Accumulative
Ruby@NTUIM
二元索引樹 > 實際應用
區間和 Range Sum
7 | 5 | 8 | 3 | -4 | 6 | 9 | 2 |
---|
Ruby@NTUIM
二元索引樹 > 實際應用
區間和 Range Sum
7 | 12 | 20 | 23 | 19 | 25 | 34 | 36 |
---|
7 | 5 | 8 | 3 | -4 | 6 | 9 | 2 |
---|
Ruby@NTUIM
二元索引樹 > 實際應用
發現問題
7 | 5 | 8 | 3 | -4 | 6 | 9 | 2 |
---|
7 | 12 | 20 | 23 | 19 | 25 | 34 | 36 |
---|
Ruby@NTUIM
二元索引樹 > 實際應用
發現問題
7 | 5 | 8 | 3 | -4 | 9 | 2 |
---|
16
7 | 12 | 20 | 23 | 19 | 25 | 34 | 36 |
---|
Ruby@NTUIM
二元索引樹 > 實際應用
發現問題
7 | 5 | 8 | 3 | -4 | 9 | 2 |
---|
16
7 | 12 | 20 | 23 | 19 |
---|
25
34
36
Ruby@NTUIM
二元索引樹 > 實際應用
發現問題
7 | 5 | 8 | 3 | -4 | 9 | 2 |
---|
16
7 | 12 | 20 | 23 | 19 |
---|
35
34
36
Ruby@NTUIM
二元索引樹 > 實際應用
發現問題
7 | 5 | 8 | 3 | -4 | 9 | 2 |
---|
16
7 | 12 | 20 | 23 | 19 |
---|
35
44
36
Ruby@NTUIM
二元索引樹 > 實際應用
發現問題
7 | 5 | 8 | 3 | -4 | 9 | 2 |
---|
16
7 | 12 | 20 | 23 | 19 |
---|
35
44
46
Ruby@NTUIM
二元索引樹 > 實際應用
單點修改 Point Update
7 | 5 | 8 | 3 | -4 | 9 | 2 |
---|
16
7 | 12 | 20 | 23 | 19 |
---|
35
44
46
Ruby@NTUIM
二元索引樹 > 實際應用
解決方案 Solution
二元索引樹
Binary Indexed Tree
Prefix Sum Quries
Point Updates
Range Updates
Constrution
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
實際應用
運作方式
運作原理
程式實作
二元索引樹
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
二元索引樹 > 運作方式
前綴和查詢 Prefix Sum Quries
Ruby@NTUIM
二元索引樹 > 運作方式
前綴和查詢 Prefix Sum Quries
Ruby@NTUIM
二元索引樹 > 運作方式
前綴和查詢 Prefix Sum Quries
Ruby@NTUIM
二元索引樹 > 運作方式
前綴和查詢 Prefix Sum Quries
Ruby@NTUIM
二元索引樹 > 運作方式
單點修改 Point Updates
Ruby@NTUIM
二元索引樹 > 運作方式
建構 Construction
1. 將 BIT 始化所有節點初始化為 0
2. 對陣列的每個位置作單點更新
複雜度分析:
共 n 次更新、每次更新 O(log n)
Ruby@NTUIM
二元索引樹 > 運作方式
建構 Construction
Construction in linear time
Credits @WilliamFiset
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
實際應用
運作方式
運作原理
程式實作
二元索引樹
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
二元索引樹 > 運作原理
16 10000
15 01111
14 01110
13 01101
12 01100
11 01011
10 01010
9 01001
8 01000
7 00111
6 00110
5 00101
4 00100
3 00011
2 00010
1 00001
前綴和查詢 Prefix Sum Quries
1. 節點編號 Least Significant Bit
= 該節點負責區間之長度
2. 負責區間從自己本身往下數
Ruby@NTUIM
二元索引樹 > 運作原理
16 10000
15 01111
14 01110
13 01101
12 01100
11 01011
10 01010
9 01001
8 01000
7 00111
6 00110
5 00101
4 00100
3 00011
2 00010
1 00001
單點修改 Point Updates
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
實際應用
運作方式
運作原理
程式實作
二元索引樹
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
二元索引樹 > 程式實作
儲存方式 Array-based
N = 16
BIT = [ 0 ] * N
因此,BIT 很適合以「陣列」形式儲存
觀察:
一個基長度為 N 之陣列所建構的 BIT 必恰有 N 個節點,
且母節點與子節點之間編號關係明確。
Pseudo Code:
Ruby@NTUIM
二元索引樹 > 程式實作
前綴和查詢 Prefix Sum Quries
def query(i):
sum = 0
while i > 0:
sum += BIT[i]
i -= lsb(i)
return sum
流程:
將索引值持續減去其本身的 Least Significant Bit,
並將所有經過節點權重相加,直到索引值被減至 0 為止。
Pseudo Code:
Ruby@NTUIM
二元索引樹 > 程式實作
def update(i, delta):
while i <= N:
BIT[i] += delta
i += lsb(i)
流程:
將索引值持續加上其本身的 Least Significant Bit,
並將所有經過節點更新,直到索引值被加至超過 N 為止。
Pseudo Code:
單點修改 Point Updates
Ruby@NTUIM
二元索引樹 > 程式實作
def lsb(x):
return x & -x
觀念:
要取得最小位元最簡單的方法是取 x 和 -x 的 bitwise and。
因為 -x 是 x 的補數 + 1 (Two's Complement)。
Pseudo Code:
二進制最小位元 Least Significant Bit
Ruby@NTUIM
二元索引樹 > 程式實作
完整範例程式碼 Example Code
Ruby@NTUIM
二元索引樹 > 程式實作
推薦資源 Recommended Resources
Ruby@NTUIM
二元索引樹
Ruby@NTUIM
實際應用
運作方式
運作原理
程式實作
二元索引樹
謝謝大家
Brought to you by
顧寬証 B10705016
Ruby@NTUIM