zoukankan      html  css  js  c++  java
  • CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    好像这个题只能Dsu On Tree?

    有根树点分治

    统计子树过x的路径

    奇偶可以xor,深度可以减,所以,w[x]x到根的链上二进制数S保留字符出现奇偶性

    mx[S]表示w[x]=S的x的最大深度

    类比点分治去做

    更新答案时候处理一个轻儿子回来更新mx[]

    重儿子贡献的答案额外处理。

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void ot(T x){x/10?ot(x/10):putchar(x%10+'0');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) printf("%lld ",a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=5e5+5;
    const int inf=0x3f3f3f3f;
    int n,m;
    struct node{
        int nxt,to;
        int val;
    }e[2*N];
    int hd[N],cnt;
    void add(int x,int y,int z){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        e[cnt].val=z;
        hd[x]=cnt;
    }
    int sz[N],son[N];
    int w[N];
    int dep[N];
    void dfs(int x,int d){
        sz[x]=1;
        dep[x]=d;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            w[y]=w[x]^(1<<e[i].val);
            dfs(y,d+1);
            sz[x]+=sz[y];
            if(sz[y]>sz[son[x]]) son[x]=y;
        }
    }
    int mx[1<<22];
    int ans[N];
    int Son;
    pair<int,int>mem[N];
    int tot;
    void upda(int x,int id,int val){
        if(val==-1) mx[w[x]]=-inf;
        if(val==1){
            ans[id]=max(ans[id],mx[w[x]]+dep[x]-2*dep[id]);
            for(reg i=0;i<22;++i){
                ans[id]=max(ans[id],mx[w[x]^(1<<i)]+dep[x]-2*dep[id]);
            }
            mem[++tot]=mk(w[x],dep[x]);
        }
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            upda(y,id,val);
        }
    }
    void sol(int x,int op){
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==son[x]) continue;
            sol(y,0);
        }
        if(son[x]) sol(son[x],1);
        mx[w[x]]=max(mx[w[x]],dep[x]);
        if(son[x]){
            ans[x]=max(ans[x],mx[w[x]]-dep[x]);
            for(reg i=0;i<22;++i){
                ans[x]=max(ans[x],mx[w[x]^(1<<i)]-dep[x]);
            }
        }
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            ans[x]=max(ans[x],ans[y]);
            if(y!=son[x]){
                tot=0;
                upda(y,x,1);
                for(reg j=1;j<=tot;++j){
                    mx[mem[j].fi]=max(mx[mem[j].fi],mem[j].se);
                }
            }
        }
        if(op==0){
            upda(x,x,-1);
        }
        
    }
    int main(){
        rd(n);
        char ch[3];
        int fa;
        memset(mx,-inf,sizeof mx);
        for(reg i=2;i<=n;++i){
            rd(fa);
            scanf("%s",ch+1);
            add(fa,i,ch[1]-'a');
        }
        dfs(1,1);
        sol(1,1);
        for(reg i=1;i<=n;++i){
            printf("%d ",ans[i]);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/3/10 10:32:24
    */

    Dsu 由于“精确打击”,可以类比点分治处理有根树的路径了。只要维护好重儿子的信息

    但是缺点同样明显:如果信息不具有可减性,就没法做了

  • 相关阅读:
    Java 如何删除 List 中的重复元素
    显示源代码及其子目录中的文件结构
    关于overflow:hidden的作用(溢出隐藏,清除浮动,解决外边塌陷等等)
    网页制作小技巧
    StringWriter/PrintWriter在Java输出异常信息中的作用
    [转载]利用@media screen实现网页布局的自适应,@media screen and
    OutputCache祥解
    string和stringBuilder区别
    sql执行顺序
    sql事务(Transaction)用法介绍及回滚实例
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10505421.html
Copyright © 2011-2022 走看看