參考自:
0. 介紹(來自wikipedia)
- 樹狀陣列, 又稱二分索引樹(binary indexed tree,bit), 用於高效計算數列的字首和.
- 它可以以
的時間得到
,並同樣以
對某項加乙個常數。
1. 資料結構定義
- 存放原始資料元素的陣列a (i.e. int a)
- 樹狀陣列 s (i.e. int s)
- 注意:
- 原始資料陣列 a 可能是隱含的, 因為 s[i] 中包含a[i], 而且也可以通過 s[i]-s[i-1] 來計算得到 a[i].
- 樹狀陣列s只是乙個維護 a 資訊的資料結構, 可能本身不對應實際的物理含義, 是一種抽象的結構.
2. 說明:
- s 和 a 的大小一樣大
- 當a全為0 的時候, s也全為0.
- s 的build 是基於維護a的, 但是a不一定是現成的, 有時候可能通過從0開始動態構建(參考題解poj 2352
).- 下標從 1 開始計算, 因為後面要用到二進位制格式末尾 連續0 的個數. 所以如果用 0 的話不太好處理.
3. 公式(2個等效的, 公式1用於理解, 計算主要用公式2)
-1.s[i]=a[i-2k+1]+a[i-2k+1+1]+......+a[i-1]+a[i] (ifi-2k+1 < i)
-2.s[i]=a[i] + s[j] (j=i-1 decreasing toi-2k+1, j -=2t, t=lowbit(j)
)- s[i] 表示 樹狀陣列第i個元素, 並不是前 i 個元素的和.
- k 表示 i 的二進位制格式的末尾連續0的位數( i.e. i=610=1102 => k = 1) , 也代表s[i] 在樹狀結構中的層數 (i.e. s[6] 在 level 1, from level 0).
- 2k 表示 s[i] 中包含原始資料 陣列 a 中的元素個數 如s[6] = a[5] + a[6], 因為 k=1, 2k為2, 利用公式計算得到 a[5] 和 a[6]. a[i-2k+1] 算出 a[5]為起始項.
4. 工具**
- 求 2k 值
int lowbit(int- 建立樹狀陣列x)
- 注意: 只有當原始資料陣列準備好之後才能用這個方法. 如果沒有, 應該使用動態構建(先初始化s, 然後根據條件構建s到完整的樹狀陣列).
//- 查詢: 求前n項和, 繼而也可以求任意區間之和. (logn)根據原始資料陣列建立樹狀陣列 s
void
build()
}
//- 修改: 修改元素資料並同步更新樹狀陣列的值.(logn)計算前n項和
int sumn (int
n)
//原始陣列可以直接修改, 更新樹狀陣列需要將包含 a[i]的所有元素更新.
//@param index: 修改的元素的下標. a[i]的修改對s[i]以前的元素沒有影響.
//@param dalta : 修改量
void modify(int index, int
delta)
學習筆記 樹狀陣列
以下 為樹狀陣列最常用的幾個操作 1.low bi t mathrm lowbit function lowbit x longint int64 begin exit x and x end 2.單點修改 procedure replace x,y int64 var i int64 begin ...
樹狀陣列學習筆記
在學習完了線段樹後,聽說樹狀陣列能寫的題,線段樹都能做,所以一直沒有詳細的學習樹狀陣列 直到碰到了一道卡線段樹的題目,因為線段樹運用了很多遞迴,所以常數比較大,容易被卡 現在總結一下樹狀陣列 1 樹狀陣列個人認為就是字首和演變而來的 2 單點更新 當你要更新某個點的值時,你要從下面到上面依次更新過去...
樹狀陣列學習筆記
樹狀陣列 binary index tree,bit 也是很多人心中最簡潔優美的資料結構之一。最簡單的樹狀陣列支援兩種操作,時間複雜度均為 當然,樹狀陣列能維護的不侷限於加法,支援的操作也不止這兩種,甚至有大佬能用樹狀陣列實現平衡樹,但這篇筆記不會深入討論 因為我也還不是很懂 回顧一下,我們說,我們...