题解:大量的工作沟通 [GESP8级]
2025-12-27 10:58:57
发布于:山东
9阅读
0回复
0点赞
发现要求的就是所有被选中员工的lca。lca(x1,x2,...,xn)=lca(lca(lca(x1,x2),x3),...)
但是因为要找编号最大的,而从lca到根结点这条链上的所有点都是满足题目要求的,所以答案应该是lca的前缀max
补充:更快的方法,一个点集的lca等于点集中dfs序最大 和 dfs序最小的结点的lca(感性理解即可)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 7;
int n, q, f[N][25], dep[N], mx[N];
vector<int> G[N];
void dfs(int u, int fa){ // 预处理深度和lca
f[u][0] = fa, dep[u] = dep[fa] + 1, mx[u] = max(u, mx[fa]);
for(int i = 1; i <= 20; i ++){
f[u][i] = f[f[u][i - 1]][i - 1];
}
for(int v : G[u]){
if(v == fa) continue;
dfs(v, u);
}
}
int lca(int u, int v){
if(dep[u] < dep[v]) swap(u, v); // dep[u]>dep[v]
int d = dep[u] - dep[v];
for(int i = 0; i <= 20; i ++){ // 跳到同一高度
if(d >> i & 1){
u = f[u][i];
}
}
if(u == v) return u;
for(int i = 20; i >= 0; i --){
if(f[u][i] != f[v][i]){
u = f[u][i], v = f[v][i];
}
}
return f[u][0];
}
void solve()
{
cin >> n;
for(int i = 1; i <= n - 1; i ++){
int f; cin >> f;
G[f].push_back(i), G[i].push_back(f);
}
dfs(0, 0);
cin >> q;
while(q --){
int m, x, y; cin >> m >> y;
for(int i = 1; i <= m-1; i ++){
cin >> x; y = lca(y, x);
}
cout << mx[y] << '\n';
}
}
signed main()
{
ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
solve();
return 0;
}
这里空空如也




有帮助,赞一个