求树上k级祖先
方法1:类似 LCA,每次倍增地往上跳即可。
Code:
int fa[N][21],dep[N];
void dfs_lca(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;(1<<i)<=dep[u];i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=h[u];i!=-1;i=pre[i]){
int j=to[i];
if(j!=father){
dfs_lca(j,u);
}
}
}
int get_fa(int u,int k){
int temp=dep[u]-k;
for(int i=20;i>=0;i--)
if(dep[fa[u][i]]>=temp)
u=fa[u][i];
return u;
}
方法2:长链剖分,每一个重链的顶端存下该链中的点(按深度有序存储)。然后 u 先跳到 u 的最远的 2i<k 级祖先,这个是 O(1)。在这个祖先 u′ 上继续跳 k−2i 次,这一次跳就直接用其顶端存贮的信息来 O(1) 找。所以预处理时间复杂度为 O(nlogn),查询时间复杂度为 O(1)。有一些证明还需看链接。
本文来自博客园,作者:bwartist,转载请注明原文链接:https://www.cnblogs.com/bwartist/p/18023358