求树上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 上继续跳 k2i 次,这一次跳就直接用其顶端存贮的信息来 O(1) 找。所以预处理时间复杂度为 O(nlogn),查询时间复杂度为 O(1)。有一些证明还需看链接。

posted @ 2024-02-20 16:11  bwartist  阅读(16)  评论(0编辑  收藏  举报