能成为回文串的显然是数量为奇数的字母小于2个。问题转化成求范围内点中各种字母总个数。
把询问离线处理,按照层数排序,就可以把每一层分开处理了。剩下的问题就是处理子树。
如果能构造出一个序列使同一棵子树的节点都连续在一起。就可以转化为一个区间查询问题。DFS对节点的访问顺序刚好满足这个性质。
在DFS过程中对每个节点重新标号,并对于每个节点,记录进入该节点时的最大标号(就是自己的标号)和出该节点的最大标号。 在区间查询时这两个标号间的所有点都在这个点的子树中。 同时用dv[i]记录第i层的所有点。
用树状数组做单点修改区间查询。每处理完一层,就把这一层的点还原,然后处理下一层。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#include <set>
#include <cmath>
#define LL long long
#define maxn 500005
#include <vector>
int N,M;
int num[maxn];
int fa[maxn];
int cnt=0;
int hs[maxn];
int sh[maxn];
int l[maxn],r[maxn];
vector <int> G[maxn];
vector <int> dv[maxn];
int idx(char c){ return c-'a'; }
struct node{
int id,pa,dept;
}Q[maxn];
bool res[maxn];
int c[30][maxn];
bool cmp(node a,node b){
return a.dept<b.dept;
}
int lowbit(int n) {
return n&(-n);
}
int sum(int x,int k){
int res=0;
while(x){
res+=c[k][x];
x-=lowbit(x);
}
return res;
}
void update(int x,int v,int k){
while(x<=N){
c[k][x]+=v;
x+=lowbit(x);
}
}
void dfs(int x,int dep){
cnt++;
hs[cnt]=x;
sh[x]=cnt;
l[sh[x]]=cnt;
dv[dep].push_back(cnt);
for(int i=0;i<G[x].size();i++){
dfs(G[x][i],dep+1);
}
r[sh[x]]=cnt;
}
bool check(int n){
int nm=0;
int ql=l[sh[Q[n].pa]],qr=r[sh[Q[n].pa]];
for(int i=0;i<26;i++){
int k=sum(qr,i)-sum(ql-1,i);
if(k&1) nm++;
}
if(nm>1) return 0;
return 1;
}
int main(){
scanf("%d%d",&N,&M);
for(int i=2;i<=N;i++){
int p;
scanf("%d",&p);
G[p].push_back(i);
}
char s[maxn];
scanf("%s",s);
for(int i=0;i<N;i++){
num[i+1]=idx(s[i]);
}
for(int i=0;i<M;i++){
scanf("%d%d",&Q[i].pa,&Q[i].dept);
Q[i].id=i;
}
sort(Q,Q+M,cmp);
dfs(1,1);
int d=Q[0].dept;
for(int i=0;i<dv[d].size();i++){
int cur=hs[dv[d][i]];
update(dv[d][i],1,num[cur]);
}
res[Q[0].id]=check(0);
for(int i=1;i<M;i++){
if(Q[i].dept!=Q[i-1].dept){
int dp=Q[i-1].dept;
for(int j=0;j<dv[dp].size();j++){
int cur=hs[dv[dp][j]];
update(dv[dp][j],-1,num[cur]);
}
dp=Q[i].dept;
for(int j=0;j<dv[dp].size();j++){
int cur=hs[dv[dp][j]];
update(dv[dp][j],1,num[cur]);
}
}
res[Q[i].id]=check(i);
}
for(int i=0;i<M;i++){
if(res[i]) printf("Yes\n");
else printf("No\n");
}
}
/*
7 3
1 1 2 2 3 3
abbcddc
1 3
2 3
3 3
*/