關於線段樹
建國中學 臺大資工 賴昭勳
先備知識
課程主題
本篇大量參考 2022 IOIC 講義
線段樹優化建圖
沒錯,線段樹是圖論
有一張有向帶權圖,一開始沒有任何邊,支援三種操作
- 加一條權重\(w\)的邊\((u, v)\)
- 對於所有\( l \leq v \leq r\),加權重\(w\)的邊\((u, v)\)
- 對於所有\( l \leq v \leq r\),加權重\(w\)的邊\((v, u)\)
\(n, q \leq 10^5, w \leq 10^9\)
看到區間操作就很想用線段樹??
節點代表的區間\([l, r]\)會連到\([l, r]\)之間的所有點
考慮線段樹形成的圖,每個父節點連一條邊權為\(0\)的邊到下面兩個子節點。那因為線段樹可以把一個區間分成\(O(\log n)\)個節點,把點\(u\)連到這些節點時就可以代表這整個區間。
在線段樹優化建圖裡面,我們利用了線段樹的結構,更有效率的連上了所有邊...
那這只限於線段樹嗎?
對於長度為\(n\)的小寫字母字串,有\(m\)個限制,每個限制為\(len, i, j\),代表從\(S_i, S_j\)開始長度為\(len\)的字串相同,有幾種字串? (模\(10^9 + 7\))
\(n \leq 10^6, m \leq 10^5\)
使用 Sparse Table 來建圖!
關鍵:可以重疊
在第\(k\)層連\((i, j)\)的邊,代表連上\((i+x, j+x), \\ \forall 0 \leq x < 2^k\)的邊
時間線段樹
跟可回溯的資料結構
有一張無向圖,每次增加一條邊或刪除一條現存的邊,操作之後問連通塊個數。
\(n \leq 5 \times 10^5, m + q \leq 5 \times 10^5\)
刪邊之後不能好好維護DSU?
具體來講,DSU是什麼?
他其實只是一個序列 \(par\),\(par[x]\)代表\(x\)在DSU裡的父親。 每次加邊的時候,這個序列的某些值會改變。
那麼,我們是不是能紀錄每次加邊的時候哪些位置改變(和他們原本的數值),刪邊再把他們改回來呢?
很不幸的,不行這樣做,因為我們只能從最後加的一條邊回溯,維護起來才是對的。
dsu 回溯的細節
-
不能路徑壓縮!(否則刪邊的時候無法復原連通塊的點)
- 用啟發式合併確保操作複雜度為\(O(\log n)\)
那麼,要如何在限制回溯順序為stack的情況下達到要做的事情呢?
使用線段樹的架構!
假設我們的線段樹的節點維護的是時間區間呢?
每一條邊會有一個存在的時間區間,把這個區間切成\(O(\log n)\)塊,我們就可以在這個線段樹由上到下DFS了。
考慮從根節點開始對線段樹DFS。
線段樹其實就是某種stack!
在線段樹上DFS,往回走的時候刪邊。
+
+
-
-
+
+
-
-
+
-
Pattern
觀察力訓練
什麼是 Pattern?
基本上,就是「轉換題目要求的條件」。
給你一個序列,假設有一張圖\(G\),如果\(i < j, a_i > a_j\)就連一條\((i, j)\)的邊,問有幾個連通塊。
有\(q\)筆單點修改,每次修改後輸出答案。
\(n, q \leq 5 \times 10^5,1 \leq a_i \leq 10^6 \)
應該可以很快發現,問的是有幾個位置\(i\),使得前\(i\)項的最大值小於後\(n - i\)項最小值。
把\(a_i\)到\(a_{i+1}\)那段當成一個區間加值,那麼只被一個區間覆蓋的地方就會符合前面的條件!
(會加兩個虛點\(a_0 = 0, a_{n+1} = inf\))
這樣修改的話也可以輕鬆處理...
註:因為是值域線段樹,兩塊之間會有重複多算的問題,這部份要再處理。
Good Subpermutations
給你一個序列,問有幾個子區間的數字是連續正整數的排列。
\(n \leq 5 \times 10^5\)
其他線段樹題目
你真的懂線段樹了嗎?
給你一個長度\(n\)的正整數序列\(a\),有\(q\)筆詢問,請計算某一個區間內的所有數的最小公倍數。\(\mod \ 10^9 + 7\)
\(n, q \leq 10^6, a_i \leq 10^6\)
給你一棵\(n\)個點的樹,邊有邊權\(w_i\)。有\(q\)次更新,每次會改變一條邊的邊權,在每次更新後輸出樹直徑(帶權)
\(n, q \leq 10^5, w_i \leq 2 \times 10^{13}\)
有一面牆由\(n\)塊木板從左到右組成,每一塊預定要塗上顏色\(c_i\)的顏料。在塗色時一次可以選一個顏色塗一個連續區間,新塗的顏色數值必須大於當前在牆上的顏色才能覆蓋。
有\(q\)筆詢問,每次問塗完區間\([l, r]\)最少需要幾次操作。
\(n, q \leq 2 \times 10^5\)
給你一個長度\(n\)的正整數序列\(a\),定義一個合法的三級跳,為三個位置\(i, j, k\)使得\(i < j < k, j - i \leq k - j\),而這個三級跳的價值為\(a_i + a_j + a_k\)。有\(q\)筆詢問,輸出區間\([l, r]\)內價值最大的三級跳。
\(n, q \leq 5\times 10^5, a_i \leq 10^8\)
更多線段樹題目
你真的真的懂線段樹了嗎?
慎入
以下的題目是比較新的 OI 題
難度可能比上一頁的更高
如果有規劃想要vir 的人可以先不要點這一區
被暴雷的話一概不負責
USACO
點開->
會按照時間順序排(舊的在上面)
JOI 們
JOI Final
JOIOC
JOISC
APIO & IOI
apio
IOI
關於線段樹
By justinlai2003
關於線段樹
- 922