線段樹入門

2021-06-30 16:48:39 字數 1884 閱讀 1561

線段樹(interval tree) 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。

上圖是一棵典型的線段樹,它對區間[1,10]進行分割,直到單個點。這棵樹的特點

是:1. 每一層都是區間[a, b]的乙個劃分,記 l = b - a

2. 一共有log2l層

3. 給定乙個點p,從根到葉子p上的所有區間都包含點p,且其他區間都不包含點p。

4. 給定乙個區間[l; r],可以把它分解為不超過2log2 l條不相交線段的並。

其中第四點並不是很顯然,圖8.1顯示了[2, 8]的分解方式,深灰色結點為分解後的

區間,淺灰色結點是遞迴分解過程中經過的結點。為了敘述方便,下面稱樹中的結點

所對應的區間為樹中區間。

從第3點和第4點可以得出結論:修改乙個點只用修改log2 l個樹中區間資訊,而統計乙個區間只需要累加2log2 l個樹中區間的資訊,且訪問的總結點數是o(log l)的。兩個操作都很容易實現。

動態統計問題i 有乙個包含n個元素的整數陣列a,每次可以修改乙個元素,也可以詢問某乙個區間[l; r]內所有元素的和。如何設計演算法,使得修改和詢問操作的時間複雜度盡量低?

方法一 直接做, 則修改操作是o(1)的, 但詢問需要進行累加, 時間複雜度為o(r ¡ l),最壞情況為o(n)。

方法二 建立一棵線段樹,每個樹中區間記錄該區間的元素和,則由剛才的結論,修改元素時只需要修改log2 l個樹中區間的元素和,而統計時只需要累加2log2 l個樹中區間的元素和,兩個操作都是o(log n)的,比方法一好很多。

動態統計問題ii 有乙個包含n個元素的整數陣列a,每次可以同時給乙個區間[l; r]內的數同時增加乙個數d(d可以為負),也可以詢問某乙個數ai的值。如何設計演算法,使得修改和詢問操作的時間複雜度盡量低?

如何快速修改乙個區間?修改乙個樹中區間[a; b]將影響到以[a; b]為根的整棵子樹和它的所有祖先,所以如果沿用剛才的線段樹定義,是不可能快速實現區間修改操作的。

解決方法是借用資料結構中常用的\懶操作"的思想,只記錄有哪些操作需要執行,而不去真正執行這些操作。換句話說,在需要給樹中區間[l; r]的元素同時增

加d時,我們只記錄\曾經有一條指令add(l, r, d)"就可以了。我們把記錄的這個值稱為樹中區間的add值,則葉結點的元素值為它所有祖先的add值之和。根據前面的結論,每一條任意區間的修改指令可以分解成2log2 l個樹中區間的修改指令,且修改操作具有疊加性,因此修改操作的時間複雜度為o(log n)。查詢操作只

需要累加葉子的所有祖先,它也是o(log n)的。

動態統計問題iii 有乙個包含n個元素的整數陣列a,每次可以同時給乙個區間[l; r]內的數同時增加乙個數d(d可以為負),也可以詢問乙個區間[l; r]內所有元素的和。如何設計演算法,使得修改和詢問操作的時間複雜度盡量低?

顯然前兩個問題都是此問題的特殊情況,因此這個問題比前兩個問題難度更大。注意到上乙個問題線段樹只能提供葉結點的真正元素和,因為對於任何乙個樹中區間[l; r]來說,影響它的指令所修改的區間不僅包括它的所有祖先,也包括它的所有後代。所以[l; r]內的所有元素和應該等於[l; r]的所有祖先的add值加上[l; r]所有後代的add值。

但後代有很多,直接累加的時間開銷過大。這裡需要再一次利用線段的樹的區間相加性質,記錄乙個附加值sum_of_add,表示以[l; r]為根的子樹上所有樹中區間的add值之和。

修改操作把區間分解為樹中區間,修改它們的add值,並且要順便修改它們父親的sum_off_add值。由於區間分解過程訪問的總結點是o(log l)的,因此修改操作是o(log n)的。

查詢操作把區間分解為樹中區間,並統計它們所有祖先的add值之和,再與這些樹中區間本身的sum_off_add相加即可。

線段樹入門

學習下 線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為...

線段樹 入門

首先線段樹形象來說就是將陣列看成乙個線段,然後不斷的進行分割,儲存在樹中的不同節點上,有點類似於b 樹的定義吧 觀察上圖,首先將整個陣列的某種資訊 最大值或者最小值等 儲存在根節點,對應 1,8 然後對 1,8 線段進行平分,得到 1,4 和 5,8 兩個線段,掛在樹的第二層。這樣節點2儲存了陣列中...

線段樹入門

建議把那個文件開啟放邊上,然後看這個。涉及到 的部分本文可能會省略。not only success 線段樹 說到線段樹,首先要明確用陣列模擬樹的概念。以一顆二叉樹為例,若根為root 為1,為了方便陣列計算,那麼它的左右兒子可以用2,3來表示,即 root 1 和 root 1 1 類似於 在這個...