[Codeforces #316 D. Tree Requests]DFS序、离线、二分
1. 题目链接
[Codeforces #316 D. Tree Requests]
2. 题意描述
给定一棵
N
个节点的树, 每个节点对应
3. 解题思路
某个字符串的某个排列能够构成回文串,当且仅当,这个字符串中的每种字符出现为奇数次的种数
≤1
,所以,可以用bitset<26> 来维护每种字符出现次数的奇偶性。
首先,求出树的dfs序,即求出每个节点进入
lb
和出来的时间编号
ub
, 并且求出每个节点的深度。这样就可以用
[lb,ub]
表示以该节点为根节点的子树。
然后,求询问离线,按照不同深度分别处理。
对于同一深度的询问。先处理出,该深度下所有节点的前缀异或和。然后对该深度下所有节点的左边界二分,对右边界再来一次二分。然后两个二分得到的值异或得到该查询的答案。
4. 实现代码
#include <bits/stdc++.h>
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<Query> 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<BITS> > 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<BITS> 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;
}