树链剖分求LCA板子
时间复杂度O(n+mlogn)
vector<int>e[maxn];
int fa[maxn],dep[maxn],son[maxn],sz[maxn];
// 存u的父节点,存u的深度,存u的重儿子,存以u为根的子树的节点数
int top[maxn];
// 存u所在重链的顶点
void dfs1(int u,int father){
fa[u]=father,dep[u]=dep[father]+1,sz[u]=1;
for(int v:e[u]){
if(v==father)continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]){
son[u]=v;
}
}
}
void dfs2(int u,int t){
top[u]=t;
if(!son[u])return;//遇到叶子节点返回
dfs2(son[u],t);//向下搜重儿子
for(int v:e[u]){
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);//搜轻儿子
}
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}