線段樹優化建圖 筆記

博客觀賞效果更佳
github
cnblogs

算法講解

其實不用講,看標題就知道這大概是一個什麼樣的算法了。

它用來解決這樣類型的問題:你要支持,從一個點往一個區間中的所有點連一條邊,或者一個區間中的所有點連一條邊(有向)。

然後你就要進行一些 最短路/強連通分量/最大流 等圖論基本操作了。

那麼這個咋整呢(⊙.⊙)

假設我們現在是從第 ⑨ 個點向 [3,6][3,6] 區間中的所有點連邊。可以如下圖處理:
在這裏插入圖片描述

先建一顆線段樹,這顆線段樹上的每一個非葉子節點都向它的兩個兒子連了一條有向邊。

接着,我們把 [3,6][3,6] 在線段樹上拆分一下,變成 [3,4]+[5,6][3,4]+[5,6]。然後我們從 99 連到線段樹節點 [3,4][3,4],還有 [5,6][5,6],這樣就可以 O(logn)O(\log n) 的時空複雜度實現一次區間連邊了,是不是很神奇呢~~(✪ω✪)

(我當時是被這個算法騷到了,嚇的我目瞪口呆)

那麼這個父子之間的有向邊,邊權多少呢?首要原則是,不能影響答案,比如你要求最大流,那麼影響答案的就是路徑最小值,此時要把邊權都設置爲 INFINF。如果是求最短路,那影響答案的就是路徑和,此時把邊權設置爲 00 就好了 (**)

然後我們怎麼從區間連向點呢?我們再建一顆樹,這顆樹的父子邊是從兒子到父親的有向邊。然後再把區間拆分一下即可,和上面基本一樣,就是反個方向☆daze~

還是那句話(韓信帶淨化),只有你們想不到,沒有出題人出不到,咱們去挑戰一把毒瘤例題咯 ~❤

起飛

T1. 超級經典のCF786B Legacy

(誒誒誒別嚇我嗷,B 題就 *2600?

(對,沒錯,這就是 div.1 的神仙,自閉了 o(╥﹏╥)o

這題基本就是板子了(板子也毒瘤的要死),支持 mm 個三種形式的連邊操作:

  1. 有向邊 uwvu\xrightarrow[w]{\qquad} v
  2. 區間連點 [l,r]wu[l,r]\xrightarrow[w]{\qquad} u
  3. 點連區間 uw[l,r]u\xrightarrow[w]{\qquad} [l,r]

然後給你源點 SS,求 SS 到每個點的最短路。

n,m105,w109n,m\le 10^5,w\le 10^9,其餘所有操作保證有意義且合法

然後,mm 指的是連邊 操作 的數量,並不代表邊數!

(邊數可能會到 O(n2)O(n^2) 級別,存不下

題解

就像上面那樣,開兩顆線段樹,然後連邊即可。我們管從父親到兒子連邊的線段樹叫“入樹”,即 TinT_{in}。它用來存儲 uw[l,r]u\xrightarrow[w]{\qquad} [l,r] 形式的邊。同理,另一顆叫“出樹”,即 ToutT_{out}。設 T[l,r]T[l,r] 表示線段樹 TT 上代表區間 [l,r][l,r] 的節點。

對於 uw[l,r]u\xrightarrow[w]{\qquad} [l,r] 的邊,就連邊 Tout[u,u]wTin[l,r]T_{out}[u,u]\xrightarrow[w]{\qquad}T_{in}[l,r]

同理,對於 [l,r]wu[l,r]\xrightarrow[w]{\qquad} u 的邊,就連邊 Tout[l,r]wTin[u,u]T_{out}[l,r]\xrightarrow[w]{\qquad}T_{in}[u,u]

還有,兩顆線段樹對應的葉子節點本質上是同一個 點,所以要連 nn 條邊權爲 00 的無向邊,把這些葉子節點合併起來。即,對於每個 ii,連邊 Tout[i,i]0Tin[i,i]T_{out}[i,i]\xrightarrow[0]{\qquad}T_{in}[i,i]

然後從 Tout[s,s]T_{out}[s,s] 跑一遍最短路即可。最後輸出記得輸出 dis[Tin[i,i]]dis[T_{in}[i,i]]

代碼

注意

剛接觸的時候,一定要想清楚 入樹出樹

(不建議背,要好好理解,看不懂的私信我

T2. libreoj2255

戳我

中文超短題意,我就不概括了。

題解

顯然,每個能引爆的所有炸彈,最後是要連續的

對於每個點,向它能一步引爆的炸彈連一條有向邊(點到區間連邊,這一步用線段樹優化)

然後維護它能到的點中,最小和最大的編號即可。這個可以 Tarjan 縮點後一遍 DFS 求出來。

然後就是硬上了…

這題比上面水的是,不用注意出樹和入樹,這題就一個入樹…

代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章