一顆二叉樹,即為t(a,b),引數a,b表示該節點表示區間[a,b]。區間長度b-a記為l。遞迴定義t[a,b]:
若區間長度l>1:區間[a
,⌊a+
b2⌋]
[ a,
⌊a+b
2⌋]為t的左兒子,區間[⌊
a+b2
⌋+1,
b][ ⌊a
+b2⌋
+1,b
]為t的右兒子。
若區間長度l=1:t為乙個葉子結點,表示區間[a]。
葉結點為區間內的所有資料點。在對分枝結點的區間中點分界時,資料點要麼落在左子樹的底層,要麼落在右子樹的底層。如果進行區間運算的話,則可能存在「跨越」的情況,刪除或插入區間內的每個點時都必須深入到葉結點,因此一般來說需要lo
g2n log
2n的時間複雜度。線段樹一方面可以方便計數,另一方面由於它實際上是排序二叉樹,所以容易找出最大值和最小值來。
線段樹一般採用結構陣列a儲存,如果結點a[i]代表區間[l,r]的話,則左兒子a[2*i]代表左子區間[l
,⌊l+
r2⌋]
[ l,
⌊l+r
2⌋],右兒子a[2*i+1]代表右子區間[⌊
l+r2
⌋+1,
r][ ⌊l
+r2⌋
+1,r
]。每個節點除需要記錄所代表區間的左右指標外,還可根據需要增設一些特殊的資料域,例如所代表的子區間是否為空;如果不為空的話,有多少線段覆蓋本子區間,或哪些資料落在本子區間內,以便插入或刪除線段時動態維護。
線段樹的基本操作包括:
在區間[l,r]插入或刪除線段操作前,需要為該區間建立一顆線段樹,依照二分策略將區間[l,r]劃分出tot(to
t≤2∗
log2
(r−l
))t ot
(tot
≤2∗l
og2(
r−l)
)個空的子區間,這些子區間暫且未被任何線段所覆蓋。tot為全域性變數,記錄一共用到了多少個節點。建樹前tot=0,建立線段樹t(l,r)的過程:
void build_tree(int l,int r,int i)
在插入、刪除線段或資料操作前,一般需要呼叫build過程,設定結點序號、左右指標和資料域初始化。 筆記 線段樹
線段樹和樹狀陣列的功能類似 但是比樹狀陣列強大的是 線段樹可以進行區間的更新操作 不只是單點更新 如把陣列1 3加5 或者把陣列5 6全部改為4 等等 但是線段樹的 量比樹狀陣列要大 記住線段樹的記憶體是普通的四倍!下面 線段樹輸入乙個陣列 改變區間l到r 使a陣列l到r每個加上d 求區間ll到rr...
線段樹學習筆記
線段樹是一種 二叉搜尋樹 與區間樹 相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。使用線段樹可以快速的查詢某乙個節點在若干條線段中出現的次數,時間複雜度為o logn 而未優化的 空間複雜度 為2n,因此有時需要離散化讓空間壓縮。以下筆記摘自lcomyn神犇部落格 1....
線段樹學習筆記
本文筆記在參考一步一步理解線段樹 tenos的基礎上形成 線段樹,也是二叉搜尋樹的一種,是基於陣列,但是優於陣列的一種資料結構。同時結合預處理 時間複雜度一般在o n 使得從原來陣列的o n 的查詢和更新複雜度降到了o logn 在處理很大資料量的資料更新和查詢最值方面變得簡單,值得一提的是,它的構...