zoukankan      html  css  js  c++  java
  • Codeforces 570D

    http://codeforces.com/contest/570/problem/D

    给一棵有根树(50w个点)(指定根是1号节点),每个点上有一个小写字母,然后有最多50w个询问,每个询问给出x和f,表示询问以x为根的子树,在第f层的所有节点上的字符能否组成一个回文串

    首先树形转线性,把每个点按照DFS序重新标号,然后开个vector记下第i层都有哪些节点,

    对于这一层的节点,维护一个前缀和,即某个字母出现过多少次,

    这样对于某个询问x,f,我们能知道x为根的子树在线性数组中的序号范围,

    然后二分查找第f层位于这个范围的点,通过前缀和就很容易求出来某个字母出现过多少次

    因为回文串中最多有一个字母出现奇数次,所以就可以判断是否是回文串。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<string>
    #include<sstream>
    #define eps 1e-9
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define MAXN 500005
    #define MAXM 40005
    #define INF 0x3fffffff
    #define PB push_back
    #define MP make_pair
    #define X first
    #define Y second
    #define clr(x,y) memset(x,y,sizeof(x));
    using namespace std;
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
    bool flag;
    
    vector<int> G[MAXN],D[MAXN];
    int op[MAXN],ed[MAXN],lin[MAXN],d[MAXN],mxdp;
    int ti[MAXN][26];
    char s[MAXN];
    int p[30];
    
    void dfs(int u,int f)
    {
        d[u]=f;
        mxdp=max(mxdp,f);
        lin[num]=u;//线性数组 
        op[u]=num;//子树的起始位置
        D[f].PB(num); //D[f]表示f层都有哪些节点
        num++;
        for (int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            dfs(v,f+1);
        }
        ed[u]=num-1;//子树的终止位置
    }
    
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (i=2;i<=n;i++)
        {
            scanf("%d",&x);
            G[x].PB(i);
        }
        scanf("%s",s+1);
        for (i=1;i<=n;i++) D[i].PB(0);
        num=1;
        dfs(1,1);
        for (i=1;i<=mxdp;i++)
        {
            for (j=1;j<D[i].size();j++)
            {
                int u=D[i][j-1];
                int v=D[i][j];
                for (k=0;k<26;k++) ti[v][k]=ti[u][k];//ti[u][k]表示节点u所在的那一层,从开始到节点u,各个字母出现的次数
    
                ti[v][s[ lin[v]  ]-'a']++;
            }
        }
    
        for (i=1;i<=m;i++)
        {
            int u,f;
            scanf("%d%d",&u,&f);
            int l=op[u],r=ed[u];
            int s=upper_bound(D[f].begin(),D[f].end(),l)-D[f].begin()-1;
            int e=upper_bound(D[f].begin(),D[f].end(),r)-D[f].begin()-1;
            if (s>=e)
            {
                printf("Yes
    ");
            }else
            {
                int cnt=0;
                e=D[f][e];
                s=D[f][s];
                for (k=0;k<26;k++)
                    if ((ti[e][k]-ti[s][k]) %2 ) cnt++;
                if (cnt>1) printf("No
    ");
                else printf("Yes
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    Django之信号
    Django缓存
    git简介
    Django request.path
    Django loaction.pathname 属性
    Ajax
    Anaconda 执行命令报ssl错误
    几行代码快速去掉迅雷临时文件的后缀
    win7 64 位安装 python,提示: 0x80240017-未指定的错误
    系统变量 %USERPROFILE%
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4760497.html
Copyright © 2011-2022 走看看