CodeForces686 D.Kay and Snowflake (每棵子树的重心)

31 篇文章 0 订阅

D.Kay and Snowflake

After the piece of a devilish mirror hit the Kay’s eye, he is no longer interested in the beauty of the roses. Now he likes to watch snowflakes.

Once upon a time, he found a huge snowflake that has a form of the tree (connected acyclic graph) consisting of n nodes. The root of tree has index 1. Kay is very interested in the structure of this tree.

After doing some research he formed q queries he is interested in. The i-th query asks to find a centroid of the subtree of the node vi. Your goal is to answer all queries.

Subtree of a node is a part of tree consisting of this node and all it’s descendants (direct or not). In other words, subtree of node v is formed by nodes u, such that node v is present on the path from u to root.

Centroid of a tree (or a subtree) is a node, such that if we erase it from the tree, the maximum size of the connected component will be at least two times smaller than the size of the initial tree (or a subtree).

Input

The first line of the input contains two integers n and q (2 ≤ n ≤ 300 000, 1 ≤ q ≤ 300 000) — the size of the initial tree and the number of queries respectively.

The second line contains n - 1 integer p2, p3, …, pn (1 ≤ pi ≤ n) — the indices of the parents of the nodes from 2 to n. Node 1 is a root of the tree. It’s guaranteed that pi define a correct tree.

Each of the following q lines contain a single integer vi (1 ≤ vi ≤ n) — the index of the node, that define the subtree, for which we want to find a centroid.

Output

For each query print the index of a centroid of the corresponding subtree. If there are many suitable nodes, print any of them. It’s guaranteed, that each subtree has at least one centroid.

Example
Input

7 4
1 1 3 3 5 3
1
2
3
5

Output

3
2
3
6

Note

在这里插入图片描述

The first query asks for a centroid of the whole tree — this is node 3. If we delete node 3 the tree will split in four components, two of size 1 and two of size 2.

The subtree of the second node consists of this node only, so the answer is 2.

Node 3 is centroid of its own subtree.

The centroids of the subtree of the node 5 are nodes 5 and 6 — both answers are considered correct.

题意:

给一棵n个点,n-1条边的树,其中点1为根,
q个询问,每个询问要求输出以x为根的子树的重心

思路:

先求出每颗子树的重心,然后对于每个询问O(1)输出
每次找到x的最大子树v,以x为根的树的重心一定在以v为根的子树的重心与x的连线上
新的重心一定在最大子树的重心到x的连线中
因为重心不降,所以不断上爬,详见代码

用到的一些性质:

以重心为根,那么所有的子树的大小都不超过整个树大小的一半。(sz[v]*2<=sz[root],root是树的重心,v的root子结点)

把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上。

一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。

code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int maxm=3e5+5;
vector<int>g[maxm];
int fa[maxm];
int sz[maxm];
int ans[maxm];
int n,q;
void dfs(int x){
    sz[x]=1;
    int len=g[x].size();
    if(len==0){//如果搜到低了
        ans[x]=x;//重心就是自己
        return ;
    }
    int root=0;
    for(int i=0;i<len;i++){
        int v=g[x][i];
        dfs(v);
        sz[x]+=sz[v];
        if(sz[v]>sz[root]){//找最大子树的根
            root=v;
        }
    }
    ans[x]=ans[root];
    while(sz[ans[x]]*2<sz[x]){//新的重心一定在最大子树的重心到x的连线中
        ans[x]=fa[ans[x]];//因为重心不降,所以不断上爬肯定有答案
    }
}
signed main(){
    scanf("%d%d",&n,&q);
    for(int i=2;i<=n;i++){
        scanf("%d",&fa[i]);
        g[fa[i]].push_back(i);
    }
    dfs(1);
    while(q--){
        int x;
        scanf("%d",&x);
        printf("%d\n",ans[x]);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值