簡單樹論

cmd 的 blog 可以參考

水平不高, 內容比較簡單.

內容難度不隨章節單增.

0. 雜七雜八

做題做到什麼東西都會扔到這裏. 想到啥寫啥.

  1. 如果要求統計樹上所有點對之間的貢獻, 可以考慮枚舉 lca. (CF1856E1)

  2. 如果有類似於樹上經過的邊的權值 \(\leq k\) 這樣的限制, 可以把邊按照邊權排序再往裏面加. 要求是能快速算出把兩個連通塊連起來的貢獻. (CF1857G)

  3. 如果所有詢問都是從根到一個結點這樣的, 可以直接在 dfs 時維護加入/撤銷. (AT_abc302_h)

  4. 把一些點連起來的最小連通塊: 利用虛樹結論, 維護 dfs 序相鄰的點, 但是寫起來簡單地多. (CF176E)

  5. 中途換根對子樹和 lca 的影響: 分類討論即可. (CF916E)

1. 重鏈剖分

用於路徑/子樹的修改詢問.

大致思路是, 嘗試用線段樹來維護 dfs 序. 子樹是容易的.

對於鏈, 如果能夠讓 dfs 序連續, 那也是容易的. 爲了儘可能做到 dfs 序的連續, 我們每次先 dfs 重兒子, 這樣形成若干條重鏈. 因爲到根的路徑可以拆成 \(O(\log n)\) 條重鏈, 該算法時間複雜度正確.

(過於簡單, 不給例題了)

2. 樹上線段樹合併

直接上題目.

例 1: P4556 [Vani有約會] 雨天的尾巴 /【模板】線段樹合併

例 2: P6773 [NOI2020] 命運

3. dsu on tree / 樹上啓發式合併

不帶修子樹詢問.

4. 長鏈剖分

這個東西可以 \(O(n\log n)-O(1)\) 求樹上 k 級祖先, 不過用處不大.

比較重要的是, 長鏈剖分可以用來優化只與深度有關的 dp.

例 1: CF1009F Dominant Indices

例 2: P5904 [POI2014] HOT-Hotels 加強版

例 3: P4292 [WC2010] 重建計劃

5. 點分治

一般用來統計路徑.

具體操作是, 選定一個點 (樹的重心), 一次做完所有經過這個點的路徑, 然後只需到各個子樹繼續統計.

例 1: P4178 Tree

簡單題. 使用點分治, 直接考慮怎麼統計經過一個點的路徑.
爲了避免統計到兩個點在一個子樹裏的情況, 我們可以對每棵子樹, 先查它的貢獻, 再加進去.
於是直接 dfs 求深度, 用個樹狀數組統計一下就完事了.
時間複雜度 \(O(n\log n\log k)\).

例 2: CF293E Close Vertices

實際上還有邊分治這樣的東西, 原理差不多, 並且只會出兩個子樹, 比較好討論. 但是邊分需要三度化, 很難寫.

6. 單側點分治

名字是隨便起的. 直接看題.

例 1: P4886 快遞員

例 2: CF566C Logistical Questions

7. 點分樹

8. 虛樹

用於每次詢問和點集有關的問題, 這時需要一個只與點集大小相關的算法而不需要原來的樹.

方法是一開始求出來每個點的 dfs 序, 然後詢問的時候, 把相鄰兩個點的 lca 拉出來建樹 (結論). 然後對着建出來的虛樹進行操作即可.

9. Kruskal 重構樹

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