Book 資料結構 線段樹 小結

2022-05-24 15:57:10 字數 1662 閱讀 6162

2014-09-12 21:49:59  -> 2014-10-04 16:59:44

花了挺長的一段時間學習線段樹,所刷的題:poj線段樹20題彙總,hdu題庫數道+比賽題2道。

線段樹這種結構,主要優勢在於把區間問題從o(n)的複雜度優化到o(logn)。

幾個注意點:

no.1:線段樹的陣列通常要開到葉子節點數的四倍(原因:剛好存滿n個節點的線段樹有趨近於2n個節點,而為了防溢位,要建出第n+1個葉子節點,那麼根節點要再開一大棵子樹出來,所以是4n)

no.2:有些線段樹題目需要離散化,而線段樹節點區間表示離散化後的值。

(1)建樹,build_tree

1、葉子節點為點的情況:

最為常見的建樹方式,邊界條件:l == r,遞迴方式:build_tree(lp,l,mid) , build_tree(rp,mid + 1,r)

2、葉子節點為單位邊的情況:

這種情況中每兩個相鄰葉子有重疊點,如 (1,2) 和 (2,3),邊界條件:l + 1 == r,遞迴方式:build_tree(lp,l,mid) , build_tree(rp,mid,r)

3、節點賦值:

可以在建樹函式中嵌入讀入語句,也可以賦值為離散化後的陣列裡的值

(2)更新,update_tree

1、點更新:

最簡單的更新方式,邊界條件:l == r ,遞迴方式:根據點的相對位置只進入左 / 右子樹中一棵

2、(需查詢型)區間更新:

批量更改點,需要用到lazy思想,如果當前區間完全包含於需更新區間,則直接更新完並返回而不繼續深入。這類更新需要在query操作,並在其中判斷是否繼續深入。因此這種情況通常讓每個樹節點維護乙個cover值,用來記錄完全更新這個含義。

邊界條件:ql <= l && r <= qr

遞迴方式:根據詢問區間,if(ql <= mid) update(左子樹), if(qr > mid) update(右子樹)

3、(無需查詢型)精確區間更新:

這類更新大多運用在掃瞄線中,精確更新的好處在於不用寫查詢函式,而每次查詢只用到根節點的資訊,這讓掃瞄線寫起來更飄逸。

邊界條件:ql == l && r == qr

遞迴方式:因為是精確更新所以要控制好進入左右子樹的區間範圍(防止死迴圈)

if(ql >= right_son_l) update_tree(ql,qr,右子樹) (左子樹完全包含更新區間)

else if(qr <= left_son_r) update_tree(ql,qr,左子樹) (右子樹完全包含更新區間)

else

(3)查詢,query

這個函式就大同小異了,邊界條件:ql <= l && r <= qr,遞迴方式:if(ql <= mid) query(左子樹), if(qr > mid) query(右子樹)

(4)下推,push_down

這個函式對應於每個節點的cover值,是lazy思想的體現。在某此更新中如果發現所遍歷到的點在之前cover非零(即有區間完全更新的含義),那麼就需要push_down函式來把當前區間的資訊下推給它的兩個子樹。注意點:下推完後自己的cover值要歸零。(這裡歸零的含義應理解為標記為沒有區間完全更新的含義)

幾個經典題目:poj 3667,這題把區間操作考察了個遍,然後每個節點需要維護的值也很多。

poj 3695,掃瞄線好題,寫完這題,掃瞄線基本上沒問題了。

資料結構 線段樹

啦啦啦啦啦啦線段樹是個好東西 好吧並沒有什麼好的 但貌似還是很好啊 線段樹就是一棵樹!顧名思義 又是這個詞 就是求關於一段的某些什麼什麼東西。比如區間最大值啊什麼的。引用百科知識 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中...

資料結構 線段樹

一 目標 1.如何快速的查詢出下列陣列arr 2,5 的和 2。以及更新arr 4 為6。用普通的方法查詢的複雜度為o n 更新的複雜度為o 1 這時候我們可以用線段樹來快速完成這些操作,複雜度為logn。二 內容 如何建立,查詢,更新線段樹。public class qurqpd int tree...

資料結構 線段樹

線段樹是一顆平衡的二叉搜尋樹,他以空間換區時間,讓線性查詢加速log級別的查詢,用到的演算法主要是二分搜尋和遞迴。例如 有陣列data 我有乙個需求,我需要頻繁的查詢區間i j的sum和。這裡先給出兩個解決方案 如果使用最普通的演算法遍歷,那麼查詢和更新的複雜度為o n 當然你還可以使用動態規劃,定...