錢菜雞水平不行,只能寫寫最近公共祖先了。
目前 oi 所流行的 \(o(nlogn) - o(1)\) 的 lca 演算法是 尤拉序 + rmq,顯然,尤拉序沒有這麼好寫,而且常數不小(序列長度兩倍),所以導致了很多情況下更多人選擇了倍增等演算法。
尤拉序+rmq 演算法中,我們要實現乙個 \(2n\) 長度的序列的 rmq,但是我們發現,我們詢問的端點數量卻最多只有 \(n\) 個,這意味這我們可以將某些連續的段給縮起來。
縮起來後就成了乙個序列 \(a\),我們記 \(idfn_i\) 為滿足 \(dfn_ = i\) 的乙個數,容易發現 \(a_i = lca(idfn_, idfn_)\),顯然,我們求 \(x, y (dfn_x <= dfn_y)\) 的 lca 只需要求出 \(a_i (dfn_x \leq i \lt dfn_y)\) 中 \(dfn\) 最小的節點 (注意,需要特判 \(x = y\))。
下面我們的問題是如何求 \(a_i\)。可以證明的是 \(a_i = lca(idfn_, idfn_) = fa_}\),因此可以在一次 \(dfs\) 內簡單的求出 \(a\) 陣列。於是我們只用做一次長度為 \(n\) 的 rmq 預處理,在 \(o(n) - o(1)\) lca 中也有不錯的優化效果。
\(o(nlogn) - o(1)\)
#includeconst int maxn = 500500;
int n, m, s;
struct t way[maxn << 1];
int h[maxn], num;
int st[20][maxn], dfn[maxn], tot;
inline int min(int x,int y)
inline void link(int x,int y) , h[x] = num;
way[++num] = , h[y] = num;
}inline void dfs(int x,int fa = 0)
inline int lca(int x,int y)
int main()
}
\(o(n) - o(1)\):
#includeconst int maxn = 1000001;
typedef unsigned u32;
struct istream
inline istream& operator >> (int & x)
} cin;
struct ostream
vout = buf + size;
} inline ~ ostream()
inline ostream& operator << (int x)
inline ostream& operator << (char x)
} cout;
int n,q;
int a[maxn],dfn[maxn],tot;
namespace rmq
inline void down(int & x,int y)
inline int qry(int l,int r)
inline int rmq(int l,int r)
inline void build(int n)
for(int i = 1;i < 15;++i)
for(int j = 0;j + (1 << i) - 1 <= n / 32;++j)
st[i][j] = min(st[i - 1][j],st[i - 1][j + (1 << i - 1)]); }}
struct t way[maxn << 1];
int h[maxn],num;
inline void adde(int x,int y), h[x]=num;
way[++num] = , h[y]=num;
}inline void dfs(int x,int f)
inline int lca(int x,int y)
int ans[maxn];
int main()
最近公共祖先 python 最近公共祖先
lca演算法樸素演算法 也就是我們所說的暴力演算法,大致的思路是從樹根開始,往下迭代,如果當前結點比兩個結點都小,那麼說明要從樹的右子樹中找 相反則從左子樹中查詢 直到找到乙個結點在當前結點的左邊,乙個在右邊,說明當前結點為最近公共祖先,如果乙個結點是另外乙個結點的祖先,那麼返回前面結點的父親結點即...
最近公共祖先 LCA 最近公共祖先
直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...
最近公共祖先 最近公共祖先(LCA)
如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。輸入格式 第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩個正整數a b,表示詢問...