2020寒假樹狀陣列學習記

2021-10-03 01:17:14 字數 2031 閱讀 1002

實際上,樹狀陣列算是線段樹的小弟角色,樹狀陣列能解決的問題線段樹一定能解決,而線段樹能解決的問題樹狀陣列卻不一定能解決。兩者都是在區間進行操作,但是樹狀陣列是不如線段樹厲害的。但是樹狀陣列的有點就在於常數小,並且短小精悍,手打的時候就幾行**快的一匹。並且lowbit函式的思想非常精妙。

位運算樹狀陣列涉及到大量的位運算,跟二進位制緊密結合。其實就是二進位制中的運算,再換回十進位制,得到結果。

先放個**:

int

lowbit

(int x)

return x&

(-x)

;

非常短小精悍吧!這可以說是樹狀陣列的精髓。而其作用是「二進位制數從低位向高位數,第乙個數字1"作為運算結果。有點難理解,for example:

lowbit(12) = 4

12的二進位制為1100,從低位到高位(右到左),碰見第乙個1時,截斷,只取下面部分作為結果,即:100,十進位制是4。

其實就是二進位制從右向左碰見第乙個1時分開這個數,右邊的部分轉化成十進位制後輸出。這樣,很明顯我們得到的結果必定是1、2、4、8、16等數(1或2^n),同時在變化的過程中不斷迴圈增大。我們只需要提供1-8的lowbit結果就可以了:

根據上面的圖,我們可以做出分析。

如果把lowbit函式的值作為這個位置儲存的區域和,這樣就可以完美覆蓋所有位置。也就是,每乙個數字管理一段區間。就像線段樹一樣。這就是為什麼我們要利用lowbit函式。

我們在維護、使用樹狀陣列的時候,利用累加。原來陣列上利用累加的時候是i++,這樣遍歷一次陣列時間複雜度為o(n),我們既然可以利用lowbit,那麼累加的時候將i++改為i += lowbit(i),這樣雖然我們還是在原陣列上跳躍,但是可以抽象成在乙個樹上按順序遍歷。

我們利用陣列查詢時候o(1)的特點,直接修改對應的數值,即:tree[index] = n。這樣是最開始的一步,接下來就是維護了。我們從index開始,根據lowbit進行遍歷,即:i += lowbit(i),每次迴圈就將tree[i] += n,這樣就保證的了樹狀陣列的更新。放個小**:

void

update

(int index,

int n)

}

操作是非常多變的,具體的操作有具體的寫法,這裡就隨便寫乙個操作了。裡面num這個全域性變數,很明顯是資料的總長度,設定成全域性變數了,當然作為引數由外面傳進來也是可以的。

這裡的區間查詢,可以說查詢的是字首和。例如我們查詢20,得到的是1-20的和,只能得到字首無法得到具體的區間值。不過問題不大,我們可以通過求兩次取差的方法獲取區間值,例如:find(right) - find(left),也可以在某個陣列上取差。

跟更新相反,我們從index開始,利用lowbit進行遞減,就可以一直減到1,就可以求出字首和了。

int

q_sum

(int n)

return ans;

}

#include

#include

#include

#include

using

namespace std;

int tree[

100010];

int num =

100005

;/*

注意這個num,應該是原陣列的長度,可以設成全域性變

量,在最初構造樹狀陣列的時候手動累加。

*/int

lowbit

(int x)

void

update

(int index,

int n)

}int

query_sum

(int n)

return ans;

}int

main()

2020寒假【gmoj1967】【數列】

2020寒假學習筆記03

實驗內容如下 請用指令碼的方式程式設計計算並輸出下列級數的前 n 項之和 sn,直到 sn 剛好大於或等於 q 為止,其中 q 為大於 0 的整數,其值通過鍵盤輸入 例如,若 q 的值為 50.0,則輸出應為 sn 50.416695。在 repl模式下測試執行,測試樣例 q 1時,sn 2 q 3...

樹狀陣列學習

之前寫的題也遇到過用樹狀陣列,當時都是現查現學,而且總是搞不懂,今天又遇到了一道求區間和的題,不管最後是不是用樹狀陣列可以a,但是既然已經想到了這,就打算好好學習一下。可惜之前查到的資料都沒有儲存記錄,所以又重新查了些資料,彙總學習如下 文末附上樹狀陣列的詳細 樹狀陣列主要用到的操作 int low...

樹狀陣列學習

我覺得,樹狀陣列挺重要的就是那個 lower x x x 我說說我的理解吧。每乙個正整數都可以拆分成 2 的某些冪之和,例如 15 8 4 2 1 6 4 2 7 4 2 1 感覺可以解釋lca的倍增跳 那麼轉換成二進位制是什麼樣的呢?15 十進位制 1111 1000 100 10 1 6 十進位...