变量
- int dep[x]:节点 x 的深度,其中根节点深度为 1。
- int mxd[x]:以节点 x 为根的子树的最大深度。
- int Log[x]:x 二进制下的最高位。
- int fa[x][j]:节点 x 的 2j 级祖先。
- int son[x]:节点 x 的重儿子。
- int top[x]:节点 x 的链顶节点。
- vector<int> up[x]:链顶节点 x 的向上节点的数组。
- vector<int> dn[x]:链顶节点 x 的向下节点的数组。
函数
- void dfs1(int x):更新祖先、深度和重儿子等信息。
- void dfs2(int x,int q):更新 up、dn 数组。
- int ask(int x,int k):询问 x 的 k 级祖先。
- void init(int rt,int n):初始化。
代码
struct LCD{
int dep[N],mxd[N],Log[N],fa[N][21],son[N],top[N];
vector<int>up[N],dn[N];
void dfs1(int x){
dep[x]=mxd[x]=dep[fa[x][0]]+1;
for(int i=1;i<=19;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
son[x]=-1;
for(int i=0;i<e[x].size();i++){
int y=e[x][i];
if(y==fa[x][0])continue;
dfs1(y);
mxd[x]=max(mxd[x],mxd[y]);
if(son[x]==-1||mxd[y]>mxd[son[x]])
son[x]=y;
}
}
void dfs2(int x,int q){
top[x]=q;
if(x==q){
for(int i=0,f=x;i<=mxd[x]-dep[x];i++)
up[x].push_back(f),f=fa[f][0];
for(int i=0,f=x;i<=mxd[x]-dep[x];i++)
dn[x].push_back(f),f=son[f];
}
if(son[x])dfs2(son[x],q);
for(int i=0;i<e[x].size();i++){
int y=e[x][i];
if(y==son[x]||y==fa[x][0])continue;
dfs2(y,y);
}
}
int ask(int x,int k){
if(!k)return x;
x=fa[x][Log[k]];
k-=(1<<Log[k]);
k-=(dep[x]-dep[top[x]]);
x=top[x];
return k>=0?up[x][k]:dn[x][-k];
}
void init(int rt,int n){
Log[0]=-1;
for(int i=1;i<=n;i++)Log[i]=Log[i>>1]+1;
dfs1(rt);dfs2(rt,rt);
}
}lcd;