「樹狀數組」第 2 節:理解預處理數組 C
我們看看樹狀數組長什麼樣。
樹狀數組的樣子
例 5
我們以一個有 8 個元素的數組 A
爲例(如上圖),在數組 A
之上建立一個數組 C
,使得數組 C
的形成如上的一個多叉樹形狀,數組 C
就形成了一個樹狀數組的結構。以下是兩點說明:
-
樹狀數組要建成動態的樹形結構嗎?
- 不用。學習過堆、線段樹的朋友一定知道,使用數組就能方便地索引左右孩子結點、雙親結點(因爲規律特別容易找到),這樣的樹就不必創建成結點、指針那樣的動態樹形結構。
-
如何解釋「前綴和」查詢和「單點更新」操作?
- 如果要查詢「前綴和(4)」,本來應該查
A1
、A2
、A3
、A4
,然後把它們相加; - 有了數組
C
之後,我們只要問C4
即可; - 我們要更新結點
A1
的值,只要自底向上更新C1
、C2
、C4
、C8
的值即可。
- 如果要查詢「前綴和(4)」,本來應該查
我們構建好數組 C
以後,就完全可以拋棄數組 A
了。
理解數組 C 的定義
-
首先我們強調一點,樹狀數組的下標從 開始,下標 號我們不用,這一點我們看到後面就會明白。我們先了解如下的定義,請大家一定先記住這些記號所代表的含義:
- 數組
C
是一個對原始數組A
的預處理數組。
- 數組
-
我們還要熟悉幾個記號。爲了方便說明,避免後面行文囉嗦,我們將固定使用記號 、 、 ,它們的定義如下:
- 記號 :表示預處理數組 的索引(十進制表示);
- 記號 :表示原始數組 的索引(十進制表示)。
我們通過以下的圖,來看看 C1
、C2
、C3
、C4
、C5
、C6
、C7
、C8
分別是如何定義的。
上面的過程我們用如下的表來表示。
數組 C 的下標與數組 A 的下標的關係
- 偉大的計算機科學家注意到上表中標註了數組 C 中的元素來自數組 A 的元素個數,它們的規律如下:
- 將數組 C 的下標 表示成二進制,從右向左數,遇到 則停止,數出 的個數記爲 ,則 的值 就是「數組 C 中的元素來自數組 A 的個數」,並且可以具體得到來自數組 A 的表示,即從當前下標 開始,從右向前數出 個數組 A 中的元素的和,即組成了
C[i]
。
- 將數組 C 的下標 表示成二進制,從右向左數,遇到 則停止,數出 的個數記爲 ,則 的值 就是「數組 C 中的元素來自數組 A 的個數」,並且可以具體得到來自數組 A 的表示,即從當前下標 開始,從右向前數出 個數組 A 中的元素的和,即組成了
下面具體說明。
- 記號 :將 的二進制表示從右向左數出的 的個數,遇到 則停止,記爲 。 我們只對數組 的索引 進行這個計算,數組 的索引 不進行相應的計算;
- 這裏理解 是如何得到的是重點。
下面我們通過兩個例子進行說明。
例 6
當 時,計算 。
- 分析:因爲 的二進制表示是 ,從右邊向左邊數,第 個是 ,因此 的個數是 ,此時 。
例 7
當 時,計算 。
分析:因爲 的二進制表示是 ,從右邊向左邊數遇到 之前,遇到了 個 ,此時 = 3。 計算出 以後, 立馬得到,爲此我們可以畫出如下表格:
我們看到 是我們最終想要的。