樹狀陣列(bit)是能夠完成下述操作的資料結構。
在解題過程中,我們有時需要維護乙個陣列的字首和s[i]=a[1]+a[2]+...+a[i]。
但是不難發現,如果我們修改了任意乙個a[i],s[i]、s[i+1]...s[n]都會發生變化。
可以說,每次修改a[i]後,調整字首和s在最壞情況下會需要o(n)的時間。
當n非常大時,程式會執行得非常緩慢。
因此,這裡我們引入「樹狀陣列」,它的修改與求和都是o(logn)的,效率非常高。
令這棵樹的結點編號為c1,c2...cn。令每個結點的值為這棵樹的值的總和,那麼容易發現:c1 = a1c2 = a1 + a2c3 = a3c4 = a1 + a2 + a3 + a4c5 = a5c6 = a5 + a6c7 = a7c8 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8...c16 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16
這裡有乙個有趣的性質:設節點編號為x,那麼這個節點管轄的區間為2^k(其中k為x二進位制末尾0的個數)個元素。因為這個區間最後乙個元素必然為ax,所以很明顯:cn = a(n – 2^k + 1) + ... + an
以上部分引自:樹狀陣列
一維 + 二維樹狀陣列 + 單點更新 + 區間更新 詳解
給定乙個初始值全為0的數列a1,a2,a3,....,an
1.給定i,計算a1+a2+....+ai
2.給定i和x,執行ai+=x
bit的求和:
計算前i項的和需要從i開始,不斷把當前位置i的值加到結果中,並從i中減去i的二進位制最低非0位對應的冪,直到i變成0為止。i的二進位制的最後乙個1可以通過i&-i得到。
int bit[max_n+1],n;
int sum(int i)
return s;
}
bit的值的更新:
使第i項的值增加x需要從i開始,不斷把當前位置i的值增加x,並把i的二進位制最低非0位對應的冪加到i上。
void add(int i,int x)
}
複雜度o(logn) 樹狀陣列 BIT
樹狀陣列模版 注意 樹狀陣列x必須 0,因為lowbit 0 0,會死迴圈 單點更新區間查詢 在log n 內修改單點,求出cnt x a 1 a x 之和 求區間 a,b 之和只要求出 sum b sum a 1 即可 define rep i,a,n for int i a i n i defi...
wenbao與樹狀陣列(BIT)
經典入門題,敵兵布陣 1 include 2 include 3 include 4using namespace std 56 int n,aa 50005 cc 50005 7 8int lowbit int x 11 12void add int x,int y 17 18 19int sum...
BIT二叉索引樹(樹狀陣列)
powered by phantom lsh將上面的求連續和問題稍微改進一下,現在需要支援一種新的操作 add x d 即把a x 增加d。這樣一來,如果通過字首和的方式計算就不能簡化計算了,因為每次修改乙個元素都要修改所有在它後面的字首和。有什麼解決辦法呢?我們需要用一種新的資料結構 bit二叉索...