ABC267F 题解

DaiRuiChen007

2022-11-24 17:35:22

Solution

# ABC267F 题解 ## 思路分析 考虑对于每个点 $u$ 选择一个距离 $u$ 最远的节点 $p$,然后将 $p$ 作为根节点,求出 $u$ 的 $k$ 级祖先即可。 注意到对于 $1\sim n$ 的每个节点,这样的 $p$ 只可能是某个直径的两个端点,因此求出直径端点 dfs 即可。 求 $k$ 级祖先的时候不用倍增,直接在树上记录上一个深度为 $x$ 的点 $d_x$,由于 dfs 序的特征,对于某个点 $u$ 其 $k$ 级祖先就是 $d_{dep_u-k}$。 时间复杂度 $\Theta(n+q)$。 ## 代码呈现 ```cpp #include<bits/stdc++.h> using namespace std; const int MAXN=2e5+1; vector <int> edge[MAXN],query[MAXN]; int ans[MAXN],node[MAXN],dis[MAXN],len; inline void dfs(int p,int f,int dep) { node[dep]=p; for(int q:query[p]) if(dep>=dis[q]) ans[q]=node[dep-dis[q]]; len=max(len,dep); for(int v:edge[p]) if(v!=f) dfs(v,p,dep+1); } signed main() { int n,q; scanf("%d",&n); for(int i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } scanf("%d",&q); for(int i=1;i<=q;++i) { int u; scanf("%d%d",&u,&dis[i]); query[u].push_back(i); } for(int turn:{0,1,2}) { int pos=node[len]; len=0; if(!turn) pos=1; dfs(pos,0,0); } for(int i=1;i<=q;++i) printf("%d\n",ans[i]?ans[i]:-1); return 0; } ```