關於線段樹

建國中學 臺大資工 賴昭勳

先備知識

課程主題

本篇大量參考 2022 IOIC 講義

 線段樹優化建圖

沒錯,線段樹是圖論

有一張有向帶權圖,一開始沒有任何邊,支援三種操作

  1. 加一條權重\(w\)的邊\((u, v)\)
  2. 對於所有\( l \leq v \leq r\),加權重\(w\)的邊\((u, v)\)
  3. 對於所有\( 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