樹狀陣列 \((binary\ \ indexed\ \ trees)\) 是一種可以支援單點修改,較快維護字首和的資料結構。他的實現方式是用乙個陣列維護乙個「樹狀」的結構(如下圖所示),記錄一些區間的區間和,實現快速計算字首和。
能看到這裡的同學應該已經對字首和不陌生了。本片部落格就不再贅述
\(lowbit\) 操作是表達二進位制下最低的 \(1\) 所表達的數值。樹狀陣列利用了這個操作。當我們定義樹狀陣列\(c\)時,\(c[i]=\sum_^ia[j]\)。
\(lowbit\)實現方式:
inline int lowbit(int x)
定義巨集也可
首先我們考慮對第\(i\)個數進行修改。理所應當我們應該修改所有管控第\(i\)個數的所有節點。我們可以觀察到,第[i]個數所對應的父親節點就是\(i+lowbit(i)\)。所以每次我們只需向上跳,直到\(i>n\)即可完成所有修改
inline void upd(int x,int k)
我們知道,\(lowbit(i)\)代表\(c[i]\)包含自身向前覆蓋的區域大小,所以我們能得出\(\sum_1^ia[i]\)就是\(c[i]+c[i-lowbit(i)]+...\)
inline int query(int x)
(注:洛谷p3374)
洛谷p3368
我們考慮對\(a[\ ]\)陣列建立乙個差分陣列\(d[\ ]\)。可以發現\(a[i]=\sum_^id[j]\)。於是這個問題就變成了乙個樹狀陣列板子題對於差分陣列建立樹狀陣列的題目。
#includeusing namespace std;
namespace enterprise
const int n=500015;
int a[n],d[n],c[n],n,m;
#define lowbit(x) (x&(-x))
inline void upd(int x,int k)
inline int query(int x)
inline void main()
for(rg int i=1;i<=m;i++)else
} }}
signed main()
區間修改查詢是一種線段樹寫起來比較方便也可用樹狀陣列維護的問題型別,而且應該是出現頻率最高的一種。
樹狀陣列的題線段樹均可解決
我樹狀陣列板子題線段樹過的
演算法學習筆記 樹狀陣列 線段樹
支援單點修改和區間查詢兩個操作,單次操作o logn tr x 陣列存的是原陣列在區間 x lowbit x x 上的和 若要將乙個數x變為v,則將x x v,即加上v x 模板如下 建立樹狀陣列 for int i 1 i n i scanf d a i for int i 1 i n i add...
樹狀陣列 小白演算法學習
在解題過程中,我們有時需要維護乙個陣列的字首和s i a 1 a 2 a i 但是不難發現,如果我們修改了任意乙個a i s i s i 1 s n 都會發生變化。可以說,每次修改a i 後,調整字首和s在最壞情況下會需要o n 的時間。當n非常大時,程式會執行得非常緩慢。因此,這裡我們引入 樹狀陣...
演算法學習 陣列
乙個陣列存放了2n 1個整數,其中有n個數出現了2次,1個數出現了1次,找出出現1次的數是多少?方法一 借助輔助陣列 長度為n 1,元素為一結構體 包含數值和 個數兩個成員 進行計數,但是時間複雜度為o n n 空間複雜度為o n 1 本來是想把val定義為結構體的,但由於結構體是值型別,不是引用型...