题目描述

Roman 种植了一棵由 n 个顶点组成的树。每个顶点包含一个小写英文字母。顶点 1 是树的根,其余 n - 1 个顶点在树中都有一个 父顶点。顶点与其父顶点之间有一条边相连。顶点 i 的父顶点是顶点 pi ,父顶点的索引总是小于顶点的索引(即 pi < i )。

顶点的深度是指从根到 v 的路径上沿边的节点数。其中,根的深度等于 1 。

如果我们可以从顶点 u 到达父顶点 v ,那么我们说顶点 u 位于顶点 v 的子树中。其中,顶点 v 位于其子树中。

罗马给出了 m 个查询,其中第 i 个查询由两个数字 vi 、 hi 组成。让我们考虑位于深度 hi 的子树 vi 中的顶点。请判断能否用这些顶点上的字母组成一个 palindrome 字符串。写在顶点上的字母可以按任何顺序重新排列,以组成一个重码字符串,但应使用所有字母。

样例

1
2
3
4
5
6
7
8
9
6 5
1 1 1 3 3
zacccd
1 1
3 3
4 1
6 1
1 2

1
2
3
4
5
Yes
No
Yes
Yes
Yes

启发式合并
记录每一层节点的信息,判断是否可以组成回文串,检查的话很简单,维护一个cnt[N][26]统计每一层各个字母出现的次数,奇数次大于1则不能组成回文串。
狠狠的被卡常,可能是写的太烂了
当然我看也有二进制异或来维护出现次数,因为出现奇数次那对应位就是1,找1的个数就是,不过这也就是常数优化,还是写的太烂了
QQ截图20240318165030.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 500010;
typedef pair<int, int> pii;

int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}

int h[N], idx, n, dep[N], sz[N], son[N], m, cnt[N][26], res[N];
string s;
struct Rec{
int k,id;
};
std::vector<Rec>q[N];
struct E{
int to, ne;
} e[N];

void add (int a, int b) {
e[idx].to = b;
e[idx].ne = h[a];
h[a] = idx++;
}

bool check (int d) {
int res = 0;
for(int i = 0; i < 26; i++) {
res += (cnt[d][i] & 1);
}
return res <= 1;
}

void dfs(int x, int fa){
sz[x]=1,
dep[x] = dep[fa] + 1;
for(int i=h[x], v; ~i; i = e[i].ne){
v = e[i].to;
if(v == fa) continue;
dfs(v,x), sz[x] += sz[v];
if(!son[x] || sz[v] > sz[son[x]]) son[x] = v;
}
}
void calc(int x,int fa,int val, int pson){
cnt[dep[x]][s[x]-'a']+=val;
for(int i=h[x], v; ~i; i = e[i].ne){
v=e[i].to;
if(v == fa || v == pson) continue;
calc(v,x,val, pson);
}
}

void dfs(int x,int fa,int keep){
for(int i=h[x], v; ~i; i = e[i].ne){
v = e[i].to;
if(v ==fa || v == son[x]) continue;
dfs(v, x, 0);
}
if(son[x]) dfs(son[x], x, 1);
calc(x,fa,1, son[x]);
for(int i=0; i < q[x].size(); i++) res[q[x][i].id] = check(q[x][i].k);
if(!keep) calc(x,fa,-1, 0);
}

signed main () {
// cin.tie(0) -> sync_with_stdio();
memset(h, -1, sizeof h);
cin >> n >> m;
for(int i = 2; i <= n; i++) {
int x = read();
add(x, i);
}
dfs(1, 0);
// cout << n << endl;
cin >> s;
s = "?" + s;
for(int i = 1; i <= m; i++) {
int v = read(), h = read();
q[v].push_back({h, i});
}
// cout << s << endl;
dfs(1, 0, false);
for(int i = 1;i <= m; i++ )
puts(res[i] ? "Yes" : "No");
return 0;
}