• codeforces 570D.Tree Requests


    [题目大意]:

    给定一棵树,树的每个节点对应一个小写字母字符,有m个询问,每次询问以vi为根节点的子树中,深度为hi的所有节点对应的字符能否组成一个回文串;

    [题目分析]:

    先画个图,可看出每次询问的所有节点都是一个从1开始bfs遍历完成的节点序列中的一段,已知深度hi的情况下,可以二分得到深度为hi的那一段的位置;

    那么如何满足找到的节点必须在以vi为根的子树内这个条件?

    可以想到dfs的时间戳,把1-n的数组按深度排序,深度相同的按照dfs时间戳排序;

    这样就可以二分得到要求的所有节点的位置;

    这样可以O(n)

    分析回文串可知,如果奇数数量的字符不超过1个,那么一定能组成回文串;

    用前缀和xor优化;

    可以做到O(nlogn);

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<iomanip>
    #include<map>
    #include<set>
    #include<vector>
    #include<ctime>
    #include<cmath>
    using namespace std;
    #define LL long long
    #define up(i,j,n) for(int i=(j);(i)<=(n);(i)++)
    #define max(x,y) ((x)<(y)?(y):(x))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define FILE "1"
    #define pii pair<int,int>
    const int maxn=503000,inf=1000000000;
    int read(){
        int x=0;bool flag=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')flag=1;ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return flag?-x:x;
    }
    struct node{
        int y,next;
    }e[maxn<<1];
    int n,m;
    int linkk[maxn],len=0,sum[maxn];
    int dfs_clock=0,fa[maxn];
    char s[maxn];
    int f[maxn];
    struct Node{
        int dep,pre,lat,id;
        bool operator<(const Node &b)const{return dep<b.dep||(dep==b.dep&&pre<b.pre);}
    }a[maxn];
    void insert(int x,int y){
        e[++len].y=y;
        e[len].next=linkk[x];
        linkk[x]=len;
    }
    void dfs(int x){
        a[x].pre=++dfs_clock;a[x].id=x;
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y==fa[x])continue;
            a[e[i].y].dep=a[x].dep+1;
            dfs(e[i].y);
        }
        a[x].lat=++dfs_clock;
    }
    void init(){
        n=read(),m=read();int x;
        up(i,2,n){
            x=read();
            insert(i,x);
            insert(x,i);
            fa[i]=x;
        }
        scanf("%s",s+1);
        a[1].dep=1;
        dfs(1);
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++)f[a[i].id]=i;
    }
    int find(int x,int Dep){
        int left=1,right=n,mid;
        int L=0,R=0;
        while(left<=right){
            mid=(left+right)>>1;
            if(a[mid].dep<Dep)left=mid+1;
            else {
                right=mid-1;
                if(a[mid].dep==Dep)L=mid;
            }
        }
        left=1,right=n,mid=0;
        while(left<=right){
            mid=(left+right)>>1;
            if(a[mid].dep<=Dep){
                left=mid+1;
                if(a[mid].dep==Dep)R=mid;
            }
            else right=mid-1;
        }
        if(!L&&!R)return 1;
        left=L,right=R;
        int u=0,v=0;
        while(left<=right){
            mid=(left+right)>>1;
            if(a[mid].pre>=a[f[x]].pre){
                right=mid-1;
                if(a[mid].pre>=a[f[x]].pre&&a[mid].pre<=a[f[x]].lat)u=mid;
            }
            else left=mid+1;
        }
        left=L,right=R;
        while(left<=right){
            mid=(left+right)>>1;
            if(a[mid].pre<=a[f[x]].lat){
                left=mid+1;
                if(a[mid].pre>=a[f[x]].pre&&a[mid].pre<=a[f[x]].lat)v=mid;
            }
            else right=mid-1;
        }
        if(!u||!v)return 1;
        int p=sum[v]^sum[u-1];
        int cnt=0;
        while(p){
            if(p&1)cnt++;
            p>>=1;
        }
        if(cnt>=2)return 0;
        else return 1;
    }
    void work(){
        int x,y;
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]^(1<<(s[a[i].id]-'a'));
        while(m--){
            x=read(),y=read();
            if(find(x,y))printf("Yes
    ");
            else printf("No
    ");
        }
    }
    int main(){
        init();
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    JSP中9大内置对象类型
    使用JSP/Servalet技术开发新闻发布系统------JSP数据交互一
    BZOJ5306: [Haoi2018]染色
    BZOJ4695: 最假女选手
    BZOJ4355: Play with sequence
    BZOJ3771: Triple
    BZOJ4057: [Cerc2012]Kingdoms
    BZOJ3302: [Shoi2005]树的双中心
    BZOJ4036: [HAOI2015]按位或
    12.24 ~ 12.30周训练计划+总结
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5962714.html
Copyright © 2020-2023  润新知