1. 程式人生 > 其它 >輕重鏈剖分

輕重鏈剖分

樹上的許多問題都可以用dfs序+線段樹予以解決。
輕重鏈剖分是通過優化dfs的順序,達到優化時間複雜度的目的。
它可以\(O(n\log^2n)\)支援鏈上加,鏈上和,子樹加,子樹和還有\(O(n\log n)\)LCA。
前置知識:dfs序,樹形dp,線段樹,沒了。

首先給出一些定義:
重兒子:子樹大小最大的兒子。只能有一個重兒子。
輕兒子:不是重兒子的兒子。
重邊:連線重兒子的邊。
輕邊:連線輕兒子的邊。
重鏈:重邊組成的鏈。

舉個例項:如下圖,加粗的為重邊,有紅點的為重兒子。

可以證明,重鏈的數目是\(O(\log n)\)級別的。這保證了輕重鏈剖分的時間複雜度。
但這樣還不夠,要支援以上的操作,我們需要記錄:

  1. \(fa[i]\)\(i\)的父親
  2. \(dep[i]\)\(i\)的深度(根節點深度為多少並不重要,不妨讓根節點深度為1)
  3. \(siz[i]\)\(i\)的子樹大小
  4. \(son[i]\)\(i\)的重兒子
  5. \(top[i]\)\(i\)所在的重鏈的深度最小的節點
  6. \(dfn[i]\)\(i\)的dfs序

我們可以兩遍dfs將這些全都求出來。第一遍dfs求出前三項,第二遍dfs求出後三項。