罗马种了一棵树,树上有n个点。每个点有一个小写英文字母。1号点是树的根,剩下的n-1个点都有一个父亲。点和父亲之间通过一个边相连。第i个点的父亲是pi,且pi<i。
一个点的深度是从根到当前点的路径上经过的点数。根的深度是1。
U在v的子树中,当且仅当u往根方向走可以到达v。特别的,v也是在v的子树中。
罗马给你m个查询,第i个查询包含两个整数vi,hi。现在收集在vi子树中且深度是hi的结点。判断一下把这些结点重新排列是否能组成一个回文。
样例解释:
一个字符串s是回文,当且仅当他正着读和反着读是一样的。空串也是回文。
第一查询中,点1包含z,可以构成回文。
第二个查询中点5和6包含c,d,这个不能组成回文。
第三个查询中,没有点是深度4的,组成一个空串。
第四个查询中,也是构成了一个空串。
第五个查询中,2,3,4符合查询条件,包含字母a,c,c。可以构成cac。
Input
单组测试数据。 第一行包含两个n, m (1≤n,m≤500000),表示树的结点数目和查询数目。 第二行有n-1个数字 p2,p3,...,pn ,表示每一个点的父亲。(1≤pi<i). 接下来一行有n个小写字母,第i个表示第i个点上面的字母。 接下来m行每一行有一个查询,包含vi, hi (1≤vi,hi≤n),表示点编号和深度。
Output
对于每一个查询,如果能够组成回文,输出Yes,否则输出No。
Input示例
6 5 1 1 1 3 3 zacccd 1 1 3 3 4 1 6 1 1 2
Output示例
Yes No Yes Yes
Yes
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN = 5e5 + 10;
struct Node
{
Node(int i, int h)
{
index = i;
height = h;
}
int index;
int height;
};
int n, m;
vector<int> child[MAXN];
vector<Node> buf[MAXN];
char val[MAXN];
void dfs(vector<int> &parent, int pos, int h)
{
parent.push_back(pos);
Node temp(pos, h + 1);
for (int i = 0; i < parent.size(); i++)
{
buf[parent[i]].push_back(temp);
}
for (int i = 0; i < child[pos].size(); i++)
{
dfs(parent, child[pos][i], h + 1);
}
parent.pop_back();
}
char num[26];
bool valid()
{
int count = 0;
for (int i = 0; i < 26; i++)
{
if (num[i] & 1)
{
count++;
}
}
if (count > 1)
{
return false;
}
return true;
}
bool cmp(const Node a, const Node b)
{
return a.height < b.height;
}
int leftMost(vector<Node> &a, int h)
{
int left = 0;
int right = a.size() - 1;
while (left < right - 1)
{
int mid = left + (right - left) / 2;
if (a[mid].height < h)
{
left = mid;
}
else
{
right = mid;
}
}
if (a[left].height == h)
{
return left;
}
else if (a[right].height == h)
{
return right;
}
return -1;
}
int rightMost(vector<Node> &a, int h)
{
int left = 0;
int right = a.size() - 1;
while (left < right - 1)
{
int mid = left + (right - left) / 2;
if (a[mid].height > h)
{
right = mid;
}
else
{
left = mid;
}
}
if (a[right].height == h)
{
return right;
}
else if (a[left].height == h)
{
return left;
}
return -1;
}
template <class T>
inline void scan_d(T &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0'), c = getchar();
}
}
int main()
{
scan_d(n);
scan_d(m);
int a;
for (int i = 2; i <= n; i++)
{
scan_d(a);
child[a].push_back(i);
}
scanf("%s", &val[1]);
vector<int> parent;
dfs(parent, 1, 0);
for (int i = 1; i <= n; i++)
{
sort(buf[i].begin(), buf[i].end(), cmp);
}
int v, h;
for (int i = 0; i < m; i++)
{
scan_d(v);
scan_d(h);
int left = leftMost(buf[v], h);
if (left < 0)
{
puts("Yes");
continue;
}
int right = rightMost(buf[v], h);
memset(num, 0, sizeof(num));
for (int j = left; j <= right; j++)
{
int value = val[buf[v][j].index] - 'a';
num[value]++;
}
if (valid())
{
puts("Yes");
}
else
{
puts("No");
}
}
return 0;
}