線段樹(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相加即可。
線段樹總結 一 入門篇
今天寫寫總結,線段樹作為乙個常考常新,每次看到了都會有 還有這種操作?的謎之資料結構,我們要記住,線段樹是序列元素個數確定的 某些特殊的題是可以離線支援刪除操作 操作支援區間的封閉性,翻轉操作只支援01序列的翻轉,整數序列的翻轉是不支援的。本篇部落格主要介紹線段樹的基本操作,也就是那些典型的線段樹題...
字典樹 Trie 入門篇
字典樹 trie 字典樹 又稱字首樹 給出字串集合 code cook five file fat,我們設根節點為空節點,那麼其trie樹如下所示 字典樹又稱字首樹,給出乙個字串集合,我們可以通過公共字首將整個字串集合存到乙個樹形結構中,一旦形成了集合中的字串,我們只需在樹上的相應節點打上標記 儲存...
WPF學習之入門篇
一 什麼事wpf 用我的話說wpf開發出來的目的就是為了替代winform的。從微軟的種種跡象來說,winform逐漸會遭到淘汰 各位winform程式設計師注意了。畢竟winform已經經歷了幾十年的發展。該有一項新技術來替代了。廢話少說,接下來我們進入正題。二 wpf和winform的區別 在用...