Codeforces 570D Tree Requests 题解&代码

上周的最后一道题解!补!完!了!
啊补题解补到想吐是什么体验…我现在算是了解了

题意:给出一颗n个点的多叉树,每个点都有一个对应字母(不唯一)和一个对应编号(唯一)。然后有m组询问,每一组询问给出一个v和一个h,表示节点v所在的子树中深度是h的节点【深度是说从根节点向下计算的总深度】中包含的字母,如果这些字母可以组成回文串,输出Yes,否则输出No

思路:dfs处理一遍dfs序,按照深度一遍一遍加树状数组= =然后离线按深度处理询问就好啦,原谅我身心俱疲实在不想多解释了,不过依稀记得有人1 << 26过了【比我快QAQ

#include<iostream>
#include<vector>
#include<stdio.h>
using namespace std;
const int maxn=500005;
vector<int> son[maxn],query[maxn],edge[maxn];
int n,m,cnt,mdep,a[maxn],fa[maxn],ans[maxn],v[maxn],h[maxn],deep[maxn],in[maxn],out[maxn];
char str[maxn];
void dfs(int u)
{
    for(int i=0;i<son[u].size();i++)
    {
        //cout<<u<<' '<<son[u][i]<<endl;
        deep[son[u][i]]=deep[u]+1;
        in[son[u][i]]=++cnt;
        edge[deep[u]+1].push_back(son[u][i]);
        dfs(son[u][i]);
        out[son[u][i]]=cnt;
    }
}
int lowbit(int x)
{
    return x&(-x);
}
void Insert(int x,int l)
{
    for(int i=x;i<maxn;i+=lowbit(i))
        a[i]+=l;
}
int getsum(int x)
{
    int r=0;
    for(int i=x;i>0;i-=lowbit(i))
        r+=a[i];
    //cout<<r<<endl;
    return r;
}
int main(void)
{
    scanf("%d%d",&n,&m);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&fa[i]);
        son[fa[i]].push_back(i);
    }
    in[1]=++cnt;
    edge[1].push_back(1);
    deep[1]=1;
    dfs(1);
    out[1]=cnt;
    //cout<<"dfs"<<endl;
    scanf("%s",str+1);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&v[i],&h[i]);
        query[h[i]].push_back(i);
        mdep=max(mdep,h[i]);
    }
    for(int i=1;i<=mdep;i++)
    {
        for(int j=0;j<26;j++)
        {
            for(int k=0;k<edge[i].size();k++)
                if(str[edge[i][k]]-'a'==j)
                    Insert(in[edge[i][k]],1);
            for(int k=0;k<query[i].size();k++)
                if((getsum(out[v[query[i][k]]])-getsum(in[v[query[i][k]]]-1))%2)
                    ans[query[i][k]]++;
            for(int k=0;k<edge[i].size();k++)
                if(str[edge[i][k]]-'a'==j)
                    Insert(in[edge[i][k]],-1);
        }
    }
    for(int i=1;i<=m;i++)
        if(ans[i]>1)printf("No\n");
        else printf("Yes\n");
    return 0;
}

你可能感兴趣的:(DFS,codeforces)