ZKW線段樹學習記錄 (1)


zkw線段樹講稿:統計的力量

1、區間求和

其實zkw線段樹的核心思想就是:用1表示根節點,那么每一個節點的值就表示以該節點編號為后綴的所有節點的和。

4=100,其恰好包括了1000=8,1001=9的值。而在X<>2^n-1時,X+1即是其兄弟右節點,X<>2^n時,X-1即是其兄弟左節點。

找第I個葉子節點(0<=i<n):

記錄線段樹有k層,則葉子節點編號為2^(n-1)+t     O(1)

區間和:

Warning:理論上能放 [0,2^N) 的樹 其實只能查詢 [1,2^N - 2] 的范圍

先找到s=s-1,t=t+1的葉子節點,然后不斷向上移,若s是左子樹,則其右兄弟必在區間內,若t是右子樹,左子樹必在區間內。然后同時s、t上移一層,直至s、t為相鄰的兄弟節點(s xor t=1)

Func Query(s,t)  // 詢問從s到t閉區間
s = s – 1, t = t + 1;  // 變為開區間
s += M, t += M;  // 找到葉子位置 M=2^(層數-1)
While not ((s xor t) == 1) do //若s與t不相鄰
If ((s and 1) == 0) Answer += Tree[s + 1]; //若s是左子樹,加上右兄弟
If ((t and 1) == 1) Answer += Tree[t – 1]; //若t是右子樹,加上左兄弟
s = s >> 1, t = t >> 1; //上移一層

因為區間和頭尾無法求,所以一般多建一層會保險一點,題目中要[0,1023],直接建一個[0,2047]的樹就行了。

2、修改

基本和線段樹相同,只不過可以直接找到葉子節點。

Func Change(n,NewValue)
n += M; //找到葉子節點編號
Tree[n] = NewValue;
While n > 1 do
n = n >> 1;
Tree[n]  = Tree[2n] + Tree[2n+1];//遞歸賦值

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM