【模板】LCA(尤拉序+RMQ)
阿新 • • 發佈:2019-02-08
完整部分點這裡
平常在資訊學競賽中求LCA一般有三種辦法:
- 用倍增法求解,預處理複雜度是 ,每次詢問的複雜度是 , 屬於線上解法。
- 利用尤拉序轉化為RMQ問題,用 ST表 求解RMQ問題,預處理複雜度 ,每次詢問的複雜度為 , 也是線上演算法。
- 採用Tarjan演算法求解,複雜度 ,屬於離線演算法。
上述三種演算法都比較常用,這篇文章主要介紹第二種解法。
先介紹一下尤拉序:
對有根樹T進行深度優先遍歷,無論是遞迴還是回溯,每次到達一個節點就把編號記錄下來,得到一個長度為 的序列,成為樹 T 的尤拉序列F。
如圖1(Inkscape手畫,略醜輕噴~):
按照深度優先遍歷我們可以得到它的尤拉序和深度序列:
序號 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
尤拉序列F | 1 | 2 | 5 | 2 | 6 | 2 | 1 | 3 | 1 | 4 | 7 | 8 | 7 | 4 | 1 |
深度序列B | 1 | 2 | 3 | 2 | 3 | 2 | 1 | 2 | 1 | 2 | 3 | 4 | 3 | 2 | 1 |
為了方便,我們定義 表示 結點的第一次出現的位置,那麼我們根據上面的表格就可以得到 個結點各自的 值:
序號 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
first() | 1 | 2 | 8 | 10 | 3 | 5 | 11 | 12 |
根據深度優先遍歷的特點,我們可以知道,對於結點 和結點 , 我們不妨假設 在 之前被遍歷,也就是說 ,那麼在 遍歷到 過程中深度最小的點就是 (這一點在Tarjan演算法中也有運用)。
這樣一來,我們就可以將 LCA 問題轉化為RMQ問題: 。
舉個栗子:
仍然以上圖為例,假定 , 在圖上很明顯能夠看出 。同時我們把代表從 遍歷到 的這個序列”抽“出來:
序號 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|
尤拉序列F’ | 6 | 2 | 1 | 3 | 1 | 4 | 7 | 8 |
深度序列B’ | 3 | 2 | 1 | 2 | 1 | 2 | 3 | 4 |
為什麼要從原序列中抽取 ~ 這個串呢?原因很簡單, , ,這個值上面的表已經給出了。
可以看出,在這個序列中,深度最小的點的序號是