輕重鏈剖分
阿新 • • 發佈:2021-07-12
樹上的許多問題都可以用dfs序+線段樹予以解決。
輕重鏈剖分是通過優化dfs的順序,達到優化時間複雜度的目的。
它可以\(O(n\log^2n)\)支援鏈上加,鏈上和,子樹加,子樹和還有\(O(n\log n)\)LCA。
前置知識:dfs序,樹形dp,線段樹,沒了。
首先給出一些定義:
重兒子:子樹大小最大的兒子。只能有一個重兒子。
輕兒子:不是重兒子的兒子。
重邊:連線重兒子的邊。
輕邊:連線輕兒子的邊。
重鏈:重邊組成的鏈。
舉個例項:如下圖,加粗的為重邊,有紅點的為重兒子。
可以證明,重鏈的數目是\(O(\log n)\)級別的。這保證了輕重鏈剖分的時間複雜度。
但這樣還不夠,要支援以上的操作,我們需要記錄:
- \(fa[i]\):\(i\)的父親
- \(dep[i]\):\(i\)的深度(根節點深度為多少並不重要,不妨讓根節點深度為1)
- \(siz[i]\):\(i\)的子樹大小
- \(son[i]\):\(i\)的重兒子
- \(top[i]\):\(i\)所在的重鏈的深度最小的節點
- \(dfn[i]\):\(i\)的dfs序
我們可以兩遍dfs將這些全都求出來。第一遍dfs求出前三項,第二遍dfs求出後三項。