Codeforces Round #316 (Div. 2) D

题意:给你一个一棵树,树上的每个节点上有一个字符,询问 v,deep, 问深度为deep的,并且属于v子树的所有字符能不能组成一个回文,是数Yes,否则No

 对于这颗树,我们可以用 时间戳 来表示点v所包含的区间

然后对于每一层我们可以把这些字符存在一个数组里面

所以要找到 属于V的字符,且在deep层

我们可以对于这一层进行二分(因为在同义层的时间时递增的)

#include<bits/stdc++.h>
using namespace std;
const int mmax = 5e5+10;
int n,m;
int depp[mmax],TT;
char p[mmax];
struct Node{
    int num[26];
};
vector<char>sum[mmax];
vector<int>ID[mmax];
vector<Node>ans[mmax];
vector<int>tp[mmax];
bool vit[mmax];
struct node{
    int st,ed;
}pp[mmax];
void dfs(int x,int cnt){
    sum[cnt].push_back(p[x]);
    ID[cnt].push_back(x);
    TT++;vit[x]=1;
    pp[x].st=TT;
    for(int i=0;i<tp[x].size();i++){
        int to=tp[x][i];
        if(!vit[to]) dfs(to,cnt+1);
    }
    pp[x].ed=TT;
}
void init(){
    for(int i=0;i<=n;i++) {
        sum[i].clear();
        tp[i].clear();
        ID[i].clear();
        ans[i].clear();
    }
    memset(ans,0,sizeof(ans));
    memset(vit,0,sizeof(vit));
}
int lfind(int l,int r,int x,int b){
    int mid,ans=mmax;
    while(l<=r){
        mid=(l+r)>>1;
        int id=ID[b][mid];
        if(pp[id].st>=pp[x].st){
            ans=mid;r=mid-1;
        }
        else l=mid+1;
    }
    return ans;
}
int rfind(int l,int r,int x,int b){
    int mid,ans=-1;
    while(l<=r){
        mid=(l+r)>>1;
        int id=ID[b][mid];
        if(pp[id].ed<=pp[x].ed){
            ans=mid;l=mid+1;
        }
        else r=mid-1;
    }
    return ans;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n>>m){
        init();
        for(int i=2;i<=n;i++){
            int a;scanf("%d",&a);
            tp[a].push_back(i);
            tp[i].push_back(a);
        }
        TT=0;
        scanf("%s",p+1);
        dfs(1,1);
        for(int i=1;i<=n;i++){
            if(sum[i].size()==0) continue;
             Node a;
            memset(a.num,0,sizeof(a.num));
            for(int j=0;j<sum[i].size();j++){
                int id=sum[i][j]-'a';
                a.num[id]++;
                ans[i].push_back(a);
            }
        }
        for(int i=0;i<m;i++){
            int a,b;scanf("%d%d",&a,&b);
            int ll,rr;
            ll=lfind(0,ans[b].size()-1,a,b);
            rr=rfind(0,ans[b].size()-1,a,b);
            if(ll>rr) puts("Yes");
            else{
                int tsum=0;
                if(ll==0){
                    tsum=0;
                    for(int j=0;j<26;j++) if(ans[b][rr].num[j]&1) tsum++;
                }
                else{
                    Node a;
                    for(int j=0;j<26;j++)
                    a.num[j]=ans[b][rr].num[j]-ans[b][ll-1].num[j];
                    tsum=0;
                    for(int j=0;j<26;j++) if(a.num[j]&1) tsum++;

                }
                if(tsum>1) puts("No");
                else puts("Yes");
            }
        }
    }
}
原文地址:https://www.cnblogs.com/ainixu1314/p/4732329.html