[Codeforces #316 D. Tree Requests]
给定一棵 N 个节点的树, 每个节点对应 26 个小写字母中的一个字母,节点 i 的深度记为 depi 。 M 次询问,每次询问节点 u 的子树中(含节点 u )的所有深度为 depi 的节点,分别取得他们对应的字母,构成一个字符串。将这个串按照某个排列,问能不能构成一个回文串。
某个字符串的某个排列能够构成回文串,当且仅当,这个字符串中的每种字符出现为奇数次的种数 ≤1 ,所以,可以用bitset<26> 来维护每种字符出现次数的奇偶性。
首先,求出树的dfs序,即求出每个节点进入 lb 和出来的时间编号 ub , 并且求出每个节点的深度。这样就可以用 [lb,ub] 表示以该节点为根节点的子树。
然后,求询问离线,按照不同深度分别处理。
对于同一深度的询问。先处理出,该深度下所有节点的前缀异或和。然后对该深度下所有节点的左边界二分,对右边界再来一次二分。然后两个二分得到的值异或得到该查询的答案。
#include
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MAXN = 500000 + 5;
const int BITS = 26;
int n, m;
char s[MAXN];
struct Edge {
int v, next;
} edge[MAXN];
int head[MAXN], tot;
struct Node {
int dep, lb, ub, mxdep;
} node[MAXN];
int nid;
vector<int> H[MAXN];
struct Query {
int id, u;
};
vector I[MAXN];
bool Ans[MAXN];
void init() {
tot = 0; nid = 0;
memset(head, -1, sizeof(head));
for(int i = 0; i < MAXN; i++) H[i].clear(), I[i].clear();
}
void add_edge(int u, int v) {
edge[tot] = Edge{v, head[u]};
head[u] = tot ++;
}
void dfs(int u, int k) {
node[u].mxdep = node[u].dep = k;
node[u].lb = ++ nid;
H[k].push_back(u);
for(int i = head[u], v; ~i; i = edge[i].next) {
v = edge[i].v;
dfs(v, k + 1);
node[u].mxdep = max(node[u].mxdep, node[v].mxdep);
}
node[u].ub = nid;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d %d", &n, &m);
init();
for(int u, v = 2; v <= n; v++) {
scanf("%d", &u);
add_edge(u, v);
}
scanf("%s", s + 1);
dfs(1, 1);
for(int i = 0, u, h; i < m; i++) {
scanf("%d %d", &u, &h);
I[h].push_back(Query{i, u});
}
vector<int> L(MAXN), R(MAXN);
vector<bitset > pre(MAXN);
for(int h = 0; h < MAXN; h++) {
int sz = I[h].size(), hsz = H[h].size();
if(sz == 0) continue;
pre[0].reset();
for(int i = 0; i < hsz; i++) {
int& u = H[h][i];
L[i] = node[u].lb;
R[i] = node[u].ub;
pre[i + 1] = pre[i];
pre[i + 1].flip(s[u] - 'a');
}
for(int i = 0; i < sz; i++) {
int& id = I[h][i].id, &u = I[h][i].u;
if(hsz == 0) Ans[id] = true;
else if(node[u].dep >= h) Ans[id] = true;
else if(node[u].mxdep < h) Ans[id] = true;
else {
int &lb = node[u].lb, &ub = node[u].ub;
int LB = lower_bound(L.begin(), L.begin() + hsz, lb) - L.begin();
int UB = upper_bound(R.begin(), R.begin() + hsz, ub) - R.begin() - 1;
if(LB > UB) {
Ans[id] = true;
continue;
}
bitset bs = pre[UB + 1] ^ pre[LB];
if(bs.count() <= 1) Ans[id] = true;
else Ans[id] = false;
}
}
}
for(int i = 0; i < m; i++) {
puts(Ans[i] ? "Yes" : "No");
}
return 0;
}