用的树链剖分,求出最近公共祖先。
然后求出1到 lca 中编号最大的点。
如果不行的话我就换倍增了
#include <bits/stdc++.h>
#define int long long
#define cin std::cin
#define cout std::cout
const int N=1e5+5;
int cnt;
int n,q,m;
int fa[N],dep[N],son[N],top[N],siz[N],id[N],wt[N],c[N];
std::vector<int>g[N];
void dfs1(int x,int f)
{
fa[x]=f;
dep[x]=dep[f]+1;
siz[x]=1;
for(register int i=0;i<g[x].size();++i)
{
int v=g[x][i];
if(v==f)continue;
dfs1(v,x);
siz[x]+=siz[v];
if(siz[son[x]]<siz[v])son[x]=v;
}
}
void dfs2(int x,int topf)
{
top[x]=topf;
id[x]=++cnt;
wt[cnt]=c[x];
if(!son[x])return;
dfs2(son[x],topf);
for(register int i=0;i<g[x].size();++i)
{
int v=g[x][i];
if(v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])std::swap(x,y);
x=fa[top[x]];
}
if(dep[x]>dep[y])std::swap(x,y);
return x;
}
int lar[N<<2];
#define lx (x<<1)
#define rx (x<<1|1)
#define mid (L+R>>1)
#define max std::max
void up(int x)
{
lar[x]=max(lar[lx],lar[rx]);
}
void build(int x,int L,int R)
{
if(L==R)
{
lar[x]=wt[L];
return;
}
build(lx,L,mid);
build(rx,mid+1,R);
up(x);
}
int query(int x,int L,int R,int l,int r)
{
if(l<=L&&R<=r)return lar[x];
int ans=-1e9-9;
if(l<=mid)ans=max(ans,query(lx,L,mid,l,r));
if(r>mid)ans=max(ans,query(rx,mid+1,R,l,r));
return ans;
}
signed main()
{
std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n;
for(register int i=1;i<n;++i)
{
int x;
cin>>x;
g[x+1].push_back(i+1);
c[i+1]=i+1;
}
c[1]=1;
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
cin>>q;
for(register int i=1;i<=q;++i)
{
cin>>m;
int xlca;
cin>>xlca;
xlca++;
for(register int j=1;j<m;++j)
{
int x;
cin>>x;
x++;
xlca=lca(xlca,x);
}
cout<<query(1,1,n,id[1],id[xlca])-1<<'\n';
}
}