树链剖分求LCA其实就是树剖的一个应用.
不会树剖的点这里.
树剖求LCA的速度还很快,O(n)预处理,O(log(n))查询,相较于倍增LCA更快,而且求LCA那部分更好写,但是dfs部分比较难写.
整个算法流程就是先两个dfs预处理,然后一个判断u与v是否在同一条重链,不在就往上跳,最后得到LCA.
至于为什么查询是O(log(n))的,因为我们可以证明重链只有log(n)条,所以是O(n)的.
代码如下:
void dfs1(int k,int fa){
nod[k].dad=fa;
nod[k].size=1;
nod[k].deep=nod[fa].deep+1;
for (int i=lin[k];i;i=e[i].next)
if (e[i].y^fa){
dfs1(e[i].y,k);
nod[k].size+=nod[e[i].y].size;
if (nod[e[i].y].size>nod[nod[k].son].size) nod[k].son=e[i].y;
}
}
void dfs2(int k,int start){
nod[k].top=start;
if (nod[k].son) dfs2(nod[k].son,start);
for (int i=lin[k];i;i=e[i].next)
if (e[i].y^nod[k].son&&e[i].y^nod[k].dad) dfs2(e[i].y,e[i].y);
}
int LCA(int u,int v){
while (nod[u].top^nod[v].top)
if (nod[nod[u].top].deep>nod[nod[v].top].deep) u=nod[nod[u].top].dad;
else v=nod[nod[v].top].dad;
return nod[u].deep<nod[v].deep?u:v;
}