樹狀陣列(binary indexed tree(b.i.t))
是乙個查詢和修改複雜度都為log(n)的資料結構。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值;經過簡單修改可以在log(n)的複雜度下進行範圍修改,但是這時只
請看下圖:
我們令每個葉節點代表每乙個元素。
現在我們變形一下,順便加上陣列的編號:
a陣列是原資料。
b陣列的節點,代表其所有子節點之和。
b[1] = a[1]
b[2] = a[1] + a[2]
b[3] = a[3]
b[4] = a[1] + a[2] + a[3] + a[4]
b[5] = a[5]
b[6] = a[5] + a[6]
b[7] = a[7]
b[8] = a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8]
這時,我們再把b陣列轉化成二進位制編碼:
可以發現:
1=(001) b[1] = a[1]
2=(010) b[2] = a[1] + a[2]
3=(011) b[3] = a[3]
4=(100) b[4] = a[1] + a[2] + a[3] + a[4]
5=(101) b[5] = a[5]
6=(110) b[6] = a[5] + a[6]
7=(111) b[7] = a[7]
8=(1000) b[8] = a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8]
對照式子可以發現b[i] = a[i-2^k+1] + a[i-2^k+2] + ......a[i](k為i的二進位制中從最低位到高位連續零的長度)例如i=8時,k=3,i=7時,k=0,i=2時,k=1。
由此我們引出了lowbit函式:
lowbit(i) = 2^k
b[i] = a[i-lowbit(i)+1] + a[i-lowbit(i)
+2] + ......a[i]
1其實......很短......背吧......int lowbit(intx)2
接著是修改函式:
1 void add(int k, intbit就是b陣列在位置k上加上num,我們用lowbit列舉出與k有關的位置,依次加上num。num)
28 }
舉個栗子:
比如我們要修改1位置的值。與之有關的是b[1] b[2] b[4] b[8]。
第一次 k = 1,bit[1] += num後,lowbit(1) = 1,k+=1;
第二次 k = 2,bit[2] += num後,lowbit(2) = 2,k+=2;
第三次 k = 4,bit[4] += num後,lowbit(4) = 4,k+=4;
第四次 k = 8,bit[8] += num後,lowbit(8) = 8;
another:
修改3位置的值。與之有關的是b[3] b[4] b[8]。
第一次 k = 3,bit[3] += num後,lowbit(3) = 1,k+=1;
第二次 k = 4,bit[4] += num後,lowbit(4) = 4,k+=4;
第三次 k = 8,bit[8] +=num後, lowbit(8) = 8;
最後是查詢操作:
在這裡,我們反著來做
1跟修改的原理是一樣的,不過是反著做,比如查詢7位置之前所有的和,就是bit[7] + bit[6] + bit[4]。int query(intk)2
9return
sum;
10 }
這裡你會想,我們的查詢函式是查詢從 1——k 的值的和,要是查詢乙個區間 l——r(包含 l 和 r 的值) 的話怎麼辦?
我們利用字首和的思想,查詢 l——r 就等於query(r) - query(l-1)。
所以,luogu p3374 樹狀陣列的模板1,就解決啦~
1 #include2 #include3 #include4using
namespace
std;
5int
n,m;
6int bit[500070],a[500070];7
int lowbit(intx)8
11void add(int k, int
num)
1218}19
int query(int
k)20
27return
sum;28}
29int
main()
3037
38for(int i=1;i<=m;i++)
3948
else
49if(c == 2
) 5055}
56return0;
57 }
樹狀陣列 講解
樹狀陣列 插點法 插線法 最常見的一種用途是求乙個數列的前n項和 比如說陣列a 吧 把他轉化一下存入樹狀陣列c 中 如 c 1 a 1 c 2 a 1 a 2 c 3 a 3 c 4 a 1 a 2 a 3 a 4 c 16 a 1 a 2 a 16 也即c n 管理著2 k個數 k代表二進位制n最...
樹狀陣列(講解 模版)
樹狀陣列 如果給定乙個陣列,要你求裡面所有數的和,一般都會想到累加。但是當那個陣列很大的時候,累加就顯得太耗時了,時間複雜度為o n 並且採用累加的方法還有乙個侷限,那就是,當修改掉陣列中的元素後,仍然要你求陣列中某段元素的和,就顯得麻煩了。所以我們就要用到樹狀陣列,他的時間複雜度為o lgn 相比...
樹狀陣列入門 簡單的原理講解
樹狀陣列可以解決什麼樣的問題 這裡通過乙個簡單的題目展開介紹,先輸入乙個長度為n的陣列,然後我們有如下兩種操作 輸入乙個數m,輸出陣列中下標1 m的字首和 對某個指定下標的數進行值的修改 多次執行上述兩種操作 尋常方法 對於乙個的陣列,如果需要求1 m的字首和我們可以將其從下標1開始對m個數進行求和...