链接
支配树,求点到根路径的并可以按 (dfs) 序排序,答案为 (sumlimits_{i=1}^n{dis[a[i]]}-sumlimits_{i=1}^{n-1}{dis[lca(a[i],a[i+1])]})。
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=2e5+10;
struct hh{
int to,nxt;
}e[N<<1];
int n,m,fir[N],num,dfn[N],fa[N][20],dep[N],a[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL void add(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
IL bool cmp1(int x,int y){return dfn[x]<dfn[y];}
IL void gx(int u){for(int i=0;fa[u][i];++i) fa[u][i+1]=fa[fa[u][i]][i];}
IL int get_lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int dis=dep[x]-dep[y],i=0;dis;dis>>=1,++i)
if(dis&1) x=fa[x][i];
if(x==y) return x;
for(int i=17;~i;--i)
if(fa[x][i]^fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void dfs(int u){dfn[u]=++num;for(int i=fir[u],v;v=e[i].to;i=e[i].nxt) dfs(v);}
int main()
{
n=in();
for(int i=1;i<=n;++i){
int j=in();
if(!j) add(0,i),dep[i]=1;
else{
for(int k=1;k<=j;++k) a[k]=in();
for(int k=2;k<=j;++k) a[1]=get_lca(a[1],a[k]);
add(a[1],i),fa[i][0]=a[1],dep[i]=dep[a[1]]+1,gx(i);
}
}
num=0,dfs(0);
m=in();
while(m--){
int k=in(),ans;
for(int i=1;i<=k;++i) a[i]=in();
sort(a+1,a+k+1,cmp1);
ans=dep[a[1]];
for(int i=2;i<=k;++i)
ans+=dep[a[i]]-dep[get_lca(a[i],a[i-1])];
printf("%d
",ans);
}
return 0;
}