题解:参考博客
由于这个是离线算法,与处理啊每个结点需要的询问,在dfs访问到该节点时一起处理,因为dfs该结点子树之前子树的信息还不在st中,dfs完后信息已经在st中,所以这两个相异或就是子树的信息了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
const int MAXN=500000+100;
struct node
{
int to,next;
}edge[MAXN*2];
int tol=0;
int head[MAXN];
void add(int u,int v)
{
edge[++tol].to=v,edge[tol].next=head[u],head[u]=tol;
edge[++tol].to=u,edge[tol].next=head[v],head[v]=tol;
}
vector<PII> query[MAXN];
int ans[MAXN],st[MAXN];
char s[MAXN];
void dfs(int x,int fa,int d)
{
st[d]^=1<<(s[x]-'a');
for(int i=0;i<query[x].size();i++) //先记录dfs之前的状态
{
PII t=query[x][i];
int j=t.fi,h=t.se;
ans[j]^=st[h];
}
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
dfs(v,x,d+1);
}
for(int i=0;i<query[x].size();i++) //与dfs后的状态比较,就可以知道该子树下的状态
{
PII t=query[x][i];
int j=t.fi,h=t.se;
ans[j]^=st[h];
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
rep(i,2,n+1)
{
int v;
scanf("%d",&v);
add(i,v);
}
scanf("%s",s+1);
rep(i,0,m)
{
int v,h;
scanf("%d%d",&v,&h);
query[v].pb(mp(i,h));
}
dfs(1,-1,1);
rep(i,0,m)
{
if(ans[i]&(ans[i]-1)) puts("No");
else puts("Yes");
}
return 0;
}