树的重心的一个妙用:一个树如果有一个子树的siz大于自身的siz,那么重心就在这个子树中,否则重心就是根节点
则递推一下就完了
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=3e5+5;
int n,m;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=0;
int siz[N],fa[N],rt[N];
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
void dfs(int v){
siz[v]=1;rt[v]=v;int maxn=0;
for(int i=head[v];i;i=nxt[i]){
if(vis[i]==fa[v]) continue;
dfs(vis[i]);
siz[v]+=siz[vis[i]];
if(siz[vis[i]]>siz[maxn]) maxn=vis[i];
}
if(siz[maxn]*2>siz[v]){
int p=rt[maxn];
while((siz[v]-siz[p])*2>siz[v]) p=fa[p];
rt[v]=p;
}
}
int main(){
n=read(),m=read();
for(int i=2;i<=n;i++) fa[i]=read(),add(i,fa[i]),add(fa[i],i);
dfs(1);
while(m--) cout<<rt[read()]<<"\n";
}