Codeforces Round #359 (Div. 2) D. Kay and Snowflake

来源:互联网 发布:知页简历 编辑:程序博客网 时间:2024/06/05 23:01

D. Kay and Snowflake

time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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

题意

定义一棵树的重心为树上的一个节点,如果删除这个节点,分开的几个部分中,最大的节点数小于等于原树的1/2。
现在给定一棵树,有q个询问,问树上某点的重心是谁

思路

q数量很大,所以肯定是预处理出每个节点的重心,然后o(1)查询。
对于重心应该有这样一个结论:设节点v上最大的子树的重心为u,那么v的重心一定出现在路径uv上。
那么我们可以通过dfs遍历每个节点,当前节点依次判断路径uv上的每个点,找到满足重心要求的即可。

代码

#include <cstdio>#include <vector>#include <algorithm>using namespace std;struct point{    int v,f,l,numson,maxson;    vector<int>son;}p[300010];int dfs(int n){    p[n].l=p[n].son.size();    if (p[n].l)    {        int be,a,b=0;        for (int i=0;i<p[n].l;i++)        {            a=dfs(p[n].son[i]);            p[n].numson+=a;            if (p[n].maxson<a)             {                be=p[p[n].son[i]].v;                p[n].maxson=a;            }        }        p[n].numson++;        do        {            int ok=1;            if (p[be].maxson*2>p[n].numson) ok=0;            if (p[be].numson*2<p[n].numson) ok=0;            if (ok)            {                p[n].v=be;                break;            }            be=p[be].f;        }while (be!=p[n].f);    }    else    {        p[n].v=n;        p[n].numson++;    }    return p[n].numson;}int main(){    int n,q,x;    scanf("%d %d",&n,&q);    for (int i=2;i<=n;i++)    {        scanf("%d",&x);        p[x].son.push_back(i);        p[i].f=x;    }       dfs(1);    for (int i=1;i<=q;i++)    {        scanf("%d",&x);        printf("%d\n",p[x].v);    }}
0 0
原创粉丝点击