题意:

一棵树,每个节点是一个字母
跟节点深度为1
问对于x的子树,深度为y的节点能否组成回文串?

题解:

这个题处处都是细节
组成回文串的话,要求至多只有一个字母出现奇数次
我们先用dfs序给树标上号,同时开vector按照顺序存下每一层的节点以及每一层in[x]
对于每一层,我们已经知道有什么节点,然后把每一层节点对应的字母存起来,这个可以用二级制来存储,对于当前一层,该层内所有字母异或起来,然后用一个vector存储,相当于存了一个前缀和,反映了前x个字母的存在情况,0为该字母不存在或为偶数,1为出现次数为奇数
对于查询的x层,深度为y的情况
先通过二分查询到in[x]和out[y]的位置,分别是l和r
如果没有查询到out[y],说明该节点没有子树,那也算回文串
然后通过w=b[deep][r]^b[deep][l-1]可以得到区间[l,r]内所以字母的存在情况
w-=(w&(-w));相当于减去一个奇数的情况,如果还有奇数就输出no,否则就是yes

代码:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
const int maxn=5e5+9;
vector<int>edge[maxn];
int in[maxn],out[maxn];
int pos[maxn];
int cnt=0;
int deep[maxn];
vector<int>poss[maxn],inn[maxn];
int maxdeep;
vector<int>b[maxn];
void dfs(int u,int fa)
{
    deep[u]=deep[fa]+1;
    maxdeep=max(maxdeep,deep[u]);
    in[u]=++cnt;
    pos[cnt]=u;
    poss[deep[u]].push_back(u);//存这一层的点 
    inn[deep[u]].push_back(in[u]);//存这一层的dfs序 
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
    out[u]=cnt;
}
int main()
{
    ios::sync_with_stdio(false);
    int m,n;
    cin>>n>>m; 
    for(int i=2;i<=n;i++)
    {
        int x;
        cin>>x;
        edge[x].push_back(i);
    }
    dfs(1,0);
    string s;
    cin>>s;
    for(int i=1;i<=maxdeep;i++)
    {
        int y=0;
        for(int j=0;j<poss[i].size();j++)//第i层的所有点 
        {
            int x=s[poss[i][j]-1]-'a';
             y^=(1<<x);
            b[i].push_back(y);
        }
    }
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        int l,r;
        l=lower_bound(inn[y].begin(),inn[y].end(),in[x])-inn[y].begin();//大于等于in[x] 
        r=upper_bound(inn[y].begin(),inn[y].end(),out[x])-inn[y].begin()-1;//大于in[x] 
        if(r<0)//说明x没有子树 
        {
            printf("Yes\n");
        //    cout<<"Yes"<<endl;
            continue;
        }
        int w;
        if(l<1)w=b[y][r];
        else if(l>0)w=b[y][l-1]^b[y][r];
        w-=(w&(-w));
        if(w==0)printf("Yes\n");
        //cout<<"Yes"<<endl;
        else printf("No\n");
        //cout<<"No";
    }
    return 0;
}