codeforces 316 D

D. Tree Requests
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Roman planted a tree consisting of n vertices. Each vertex contains a lowercase English letter. Vertex 1 is the root of the tree, each of the n - 1 remaining vertices has a parent in the tree. Vertex is connected with its parent by an edge. The parent of vertex i is vertex pi, the parent index is always less than the index of the vertex (i.e., pi < i).

The depth of the vertex is the number of nodes on the path from the root to v along the edges. In particular, the depth of the root is equal to 1.

We say that vertex u is in the subtree of vertex v, if we can get from u to v, moving from the vertex to the parent. In particular, vertex v is in its subtree.

Roma gives you m queries, the i-th of which consists of two numbers vihi. Let's consider the vertices in the subtree vi located at depthhi. Determine whether you can use the letters written at these vertices to make a string that is a palindrome. The letters that are written in the vertexes, can be rearranged in any order to make a palindrome, but all letters should be used.

Input

The first line contains two integers nm (1 ≤ n, m ≤ 500 000) — the number of nodes in the tree and queries, respectively.

The following line contains n - 1 integers p2, p3, ..., pn — the parents of vertices from the second to the n-th (1 ≤ pi < i).

The next line contains n lowercase English letters, the i-th of these letters is written on vertex i.

Next m lines describe the queries, the i-th line contains two numbers vihi (1 ≤ vi, hi ≤ n) — the vertex and the depth that appear in thei-th query.

Output

Print m lines. In the i-th line print "Yes" (without the quotes), if in the i-th query you can make a palindrome from the letters written on the vertices, otherwise print "No" (without the quotes).

Sample test(s)
input
6 5
1 1 1 3 3
zacccd
1 1
3 3
4 1
6 1
1 2
output
Yes
No
Yes
Yes
Yes
Note

String s is a palindrome if reads the same from left to right and from right to left. In particular, an empty string is a palindrome.

Clarification for the sample test.

In the first query there exists only a vertex 1 satisfying all the conditions, we can form a palindrome "z".

In the second query vertices 5 and 6 satisfy condititions, they contain letters "с" and "d" respectively. It is impossible to form a palindrome of them.

In the third query there exist no vertices at depth 1 and in subtree of 4. We may form an empty palindrome.

In the fourth query there exist no vertices in subtree of 6 at depth 1. We may form an empty palindrome.

In the fifth query there vertices 2, 3 and 4 satisfying all conditions above, they contain letters "a", "c" and "c". We may form a palindrome "cac".


题解:

考查dfs序,先dfs一遍,记录每个点的dfs时进入和退出的时间点,则在这两个时间点之内的所有点均为该点子树上的点,而且在每个深度上某个点子树上所有深度相同的点在该深度集合中保持连续。

#include <bits/stdc++.h>

using namespace std;
#define N 500000 + 10
int n, m;
char s[N];
vector<int> G[N];
vector<int> D[N];
vector<int> S[N];
int rp[N], top, L[N], R[N], dep[N];

void init()
{
    top = 0;
    for(int i = 0; i <= n; i++)
    {
        G[i].clear();
        D[i].clear();
        S[i].clear();
    }
}

void dfs(int u, int deep)
{
    L[u] = ++top;
    dep[u] = deep;
    D[deep].push_back(top);
    rp[top] = u;

    for(int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i];
        dfs(v, deep + 1);
    }

    R[u] = top;
}

int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        init();
        int u;
        for(int i = 2; i <= n; i++)
        {
            scanf("%d", &u);
            G[u].push_back(i);
        }
        scanf("%s", s + 1);
        dfs(1, 1);

        for(int i = 1; i <= n; i++)
        {
            int sz = D[i].size();
            if(sz)
            {
                for(int j = 0; j < sz; j++)
                {
                    S[i].push_back(0);
                    int t = s[rp[D[i][j]]] - 'a';
                    S[i][j] = (1 << t);
                }
                for(int j = 1; j < sz; j++)
                S[i][j] ^= S[i][j-1];
            }
        }

        int h, l, r;
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d", &u, &h);
            int sz = D[h].size();
            l = L[u];
            r = R[u];
            if(dep[u] >= h || !sz || l >= D[h][sz-1] || r <= D[h][0])
            {
                printf("Yes\n");
                continue;
            }
            int x = lower_bound(D[h].begin(), D[h].end(), l) - D[h].begin();
            int y = lower_bound(D[h].begin(), D[h].end(), r) - D[h].begin();
            if(y == sz || r < D[h][y]) y--;
            int ans = S[h][y];
            if(x) ans ^= S[h][x-1];
            int flag = 0;
            //cout<<"ans :"<<ans<<endl;
            while(ans)
            {
                if(ans % 2) flag++;
                ans /= 2;
            }
            printf("%s\n", flag > 1 ? "No" : "Yes");
        }
     }
    return 0;
}


你可能感兴趣的:(ACM,codeforces)