【思维题】 Codeforces 570D Tree Requests

通道

题意:一棵树,每个节点有一个点值(字符),问u子树的深度为k的所有节点组成的字符串是否为回文

思路:搜出dfs序及该节点的深度,那么u节点深度为K的那一段肯定在dfs序[l,r]区间内,然后对于回文的处理,要么这段异或和为0,要么lowbit(x)=x

代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 500005;

typedef pair <int, int> PII;
vector <int> E[maxn];
vector <PII> H[maxn];

int dep[maxn], l[maxn], r[maxn], dfs_clock = 0;
char str[maxn];

void dfs(int x, int d) {
    dep[x] = d;
    l[x] = ++dfs_clock;
    for(int i : E[x]) {
        dfs(i, d + 1);
    }
    r[x] = dfs_clock;
}
int lowbit(int x) {
    return x & -x;
}
int main() {
    int n, m, x, y, v, h;
    scanf("%d%d", &n, &m);
    for(int i = 2; i <= n; i++) {
        scanf("%d", &x);
        E[x].push_back(i);
    }
    scanf("%s", str + 1);
    dfs(1, 1);
    for(int i = 1; i <= n; i++) H[i].push_back(make_pair(0, 0));
    for(int i = 1; i <= n; i++) {
        H[dep[i]].push_back(make_pair(l[i], 1 << (str[i] - 'a')));
    }
    for(int i = 1; i <= n; i++) {
        sort(H[i].begin(), H[i].end());
        for(int j = 1; j < H[i].size(); j++) H[i][j].second ^= H[i][j - 1].second;
    }
    while(m--) {
        scanf("%d%d", &v, &h);
        int R = upper_bound(H[h].begin(), H[h].end(), make_pair(r[v], 1 << 30)) - H[h].begin();
        int L = upper_bound(H[h].begin(), H[h].end(), make_pair(l[v], 0)) - H[h].begin();
        int X = H[h][R - 1].second ^ H[h][L - 1].second;
        if((R - L) & 1) {
            printf("%s\n", lowbit(X) == X ? "Yes" : "No");
        } else {
            printf("%s\n", X == 0 ? "Yes" : "No");
        }
    }
    return 0;
}
View Code

 

posted @ 2015-08-14 13:09  mithrilhan  阅读(182)  评论(0编辑  收藏  举报