【思维题】 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; }