题意:
给定n个点的树,m个询问
1是root,下面给出2——n每个点的父节点,
每个点有一个字母
下面n个小写字母给出每个点的字母。
下面m行给出询问:
询问形如 (u, deep) 问u点的子树中,距离根的深度为deep的所有点的字母能否在任意排列后组成回文串,能输出Yes.不能输出No
根到根的deep = 1,以此类推。
思路:
dfs序,给点重新标号,dfs进入u点的时间戳记为l[u], 离开的时间戳记为r[u], 这样对于某个点u,他的子树节点对应区间都在区间 [l[u], r[u]]内。
把距离根深度相同的点都存到vector里 D[i] 表示深度为i的所有点,在dfs时可以顺便求出。
把询问按深度排序,query[i]表示所有深度为i的询问。
接下来按照深度一层层处理。
对于第i层,把所有处于第i层的节点都更新到26个树状数组上。
然后处理询问,直接查询树状数组上有多少种字母是奇数个的,显然奇数个字母的种数要<=1
处理完第i层,就把树状数组逆向操作,相当于清空树状数组
注意的一个地方就是 询问的深度是任意的,也就是说可能超过实际树的深度,也可能比当前点的深度小。所以需要初始化一下答案。
代码如下:
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int, int>pii;
const int N = 5e5+10;
int n, m;
int l[N], r[N], top;
char s[N];
vector<int> G[N], D[N];
vector<pii> Q[N];
bool ans[N];
struct node
{
int maxn, c[N];
void init(int n)
{
maxn = n; memset(c, 0, sizeof(c));
}
inline int Lowbit(int x){return x&(-x);}
void change(int u, int x)
{
while(u <= maxn)
{
c[u] += x;
u += Lowbit(u);
}
}
int sum(int x)
{
int ans = 0;
for(int i = x; i >= 1; i -= Lowbit(i))
{
ans += c[i];
}
return ans;
}
int query(int l, int r)
{
return sum(r) ^ sum(l-1);
}
}t[26];
void dfs(int u, int fa, int dep)
{
D[dep].push_back(u);
l[u] = ++top;
for(vector<int>::iterator i = G[u].begin(); i != G[u].end(); i++)
{
if(*i != fa)
{
dfs(*i, u, dep+1);
}
}
r[u] = top;
}
int main()
{
scanf("%d%d", &n, &m);
fill(ans, ans + m + 10, 1);
for (int i = 0; i < 26; i++) t[i].init(n);
for(int i = 2, u; i <= n; i++)
{
scanf("%d", &u);
G[u].push_back(i);
}
top = 0;
dfs(1, 1, 1);
scanf("%s", s+1);
for(int i = 1, u, v; i <= m; i++)
{
scanf("%d%d", &u, &v);
Q[v].push_back(pii(u, i));
}
for(int i = 1; i <= n; i++)
{
if(D[i].size() == 0) break;
for(vector<int>::iterator j = D[i].begin(); j != D[i].end(); j++)
{
t[s[*j] - 'a'].change(l[*j], 1);
}
for(int v = 0; v < Q[i].size(); v++)
{
pii p = Q[i][v];
int cnt = 0;
for(int k = 0; k < 26; k ++)
{
if(t[k].query(l[p.first], r[p.first]))
cnt += t[k].query(l[p.first], r[p.first]) & 1;
}
ans[p.second] = cnt <= 1;
}
for(vector<int>::iterator iter = D[i].begin(); iter != D[i].end(); iter++)
{
t[s[*iter] - 'a'].change(l[*iter], -1);
}
}
for(int i = 1; i <= m; i++)
{
ans[i] ? puts("Yes") : puts("No");
}
return 0;
}