zoukankan      html  css  js  c++  java
  • 570D Codeforces Round #316 (Div. 2) D(dfs序,时间戳,二分

    题目:一棵树上每个节点有个字符值,询问每个节点的深度为h的子节点的字符是否能组成一个回文串。

    思路:首先是奇妙的dfs序和时间戳,通过记录每个节点的dfs进出时间,可以发现某个节点的子节点的进出时间均在该节点的进出时间范围内(这是很直观的dfs的性质),这样可以把树形结构转变为线性结构,方便进行各种处理。dfs一遍处理时间戳,每个节点的深度,并记录每个深度的节点都有哪些,此时每个深度的节点就是排好序的。然后对于一个询问,可以利用二分查找确定子节点在该层的哪一段。对于每一层,预先处理每个字符的前缀和,就可以做到O(1)查询区间数量。由于这题只要求奇偶性,故只需要记录01,又因为字符集为26,可以直接用int类型压位。

    ps:二分直接用的stl的,结果反而写得像一坨翔一样= =

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=5e5+3000;
    int n,m;
    vector<int> G[maxv];
    vector<int> D[maxv];
    vector<int> num[maxv];
    int deep[maxv];
    int in[maxv],out[maxv];
    char s[maxv];
    int clo=0;
    void dfs(int v,int d,int f){
        D[d].pb(v);
        deep[v]=d;
        in[v]=++clo;
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(u==f) continue;
            dfs(u,d+1,v);
        }
        out[v]=++clo;
    }
    void cul(){
        for(int i=1;i<=n;i++){
            if(D[i].size()==0){
                break;
            }
            num[i].pb(1<<(s[D[i][0]-1]-'a'));
            for(int j=1;j<D[i].size();j++){
                int c=s[D[i][j]-1]-'a';
                num[i].pb(num[i].back()^(1<<c));
            }
        }
    }
    bool cmpl(const int &va,const int &vb){return in[va]<vb;}
    bool cmpr(const int &va,const int &vb){return out[va]<vb;}
    int cas=0;
    int main(){
    //    freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=2;i<=n;i++){
            int p;
            scanf("%d",&p);
            G[p].pb(i);
        }
        scanf("%s",s);
        dfs(1,1,-1);
        cul();
        while(m--){
            int v,h;
            scanf("%d%d",&v,&h);
            int l=in[v],r=out[v],sd=h;
            if(deep[v]>h){
                puts("Yes");
                continue;
            }
            vector<int>::iterator itl=LB(D[sd].begin(),D[sd].end(),l,cmpl);
            vector<int>::iterator itr=LB(D[sd].begin(),D[sd].end(),r,cmpr);
            if(itr!=D[sd].begin()&&((itr!=D[sd].end()&&out[*itr]>r)||itr==D[sd].end())) itr--;
            if(itl!=D[sd].end()&&itr!=D[sd].end()&&in[*itl]>=l&&out[*itr]<=r){
                int dl=itl-D[sd].begin();
                int dr=itr-D[sd].begin();
                int nu=(dl>0?num[sd][dl-1]:0);
                if(nu^num[sd][dr]){
                    if(__builtin_popcount(nu^num[sd][dr])<2)
                        puts("Yes");
                    else{
                        puts("No");
                    }
                }else{
                    puts("Yes");
                }
            }else{
                puts("Yes");
                continue;
            }
        }
    }
    View Code
  • 相关阅读:
    MacOS Catalina 10.15安装教程,启动U盘制作及安装方法
    苹果macOS Catalina 10.15 正式版推送了,要不要升级,需要注意什么?
    Sublime Text Mac如何进行按键绑定?
    Mac软件应用程序打开出现意外退出、崩溃解决办法
    使用VScode Mac版编译配置C/C++程序完整图文教程
    pycharm pro 2019 mac重构技巧?
    一体化数据库管理Navicat Premium for Mac的命令提示代码
    jsonp理解
    linux系统命令大全
    java学习笔记之分层增删改查
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4731543.html
Copyright © 2011-2022 走看看