zoukankan      html  css  js  c++  java
  • Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

      感觉dsu on tree一定程度上还是与点分类似的。考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可。

      重排后可以变成回文串相当于出现奇数次的字母不超过1个。考虑dsu on tree,容易想到遍历时记录每种情况的最大深度,合并时类似点分的逐个计算贡献再合并即可。这里有个问题是得到某子树信息后,对于原来的根来说,这个信息还要再加上一个偏移量,但直接暴力显然复杂度就不对了。实际上维护信息过程中不断传递偏移量即可。

      一开始就发现了这个题只开了256M,于是机智的开了个map,悲惨的T掉了。然而题面里深藏不露的说了一句字母范围在a~v。这啥思博题啊。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 500010 
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,a[N],p[N],fa[N],size[N],deep[N],son[N],len[N],ans[N],t,f[1<<22];
    struct data{int to,nxt;
    }edge[N];
    void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],len[y]=z,p[x]=t;}
    void make(int k)
    {
        size[k]=1;
        for (int i=p[k];i;i=edge[i].nxt)
        {
            deep[edge[i].to]=deep[k]+1;
            make(edge[i].to);
            size[k]+=size[edge[i].to];
            if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to;
        }
    }
    inline int rev(int x){return (1<<22)-1^x;} 
    void update(int k,int x,int op)
    {
        if (op==1) f[k]=max(f[k],x);
        else f[k]=0;
    }
    void add(int k,int x,int op)//对子树内统计信息时,偏移量为x 
    {
        update(x,deep[k],op);
        for (int i=p[k];i;i=edge[i].nxt)
        add(edge[i].to,x^(1<<len[edge[i].to]),op);
    }
    int calc(int k,int x)
    {
        int ans=f[x]+deep[k];
        for (int i=0;i<22;i++) ans=max(ans,deep[k]+f[x^(1<<i)]);
        if (ans==deep[k]) ans=-N;
        for (int i=p[k];i;i=edge[i].nxt)
        ans=max(ans,calc(edge[i].to,x^(1<<len[edge[i].to])));
        return ans;
    }
    int dfs(int k)//获得的该子树信息的偏移量 
    {
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=son[k])
        {
            int delta=dfs(edge[i].to);
            ans[k]=max(ans[k],ans[edge[i].to]);
            add(edge[i].to,delta,-1);
        }
        int delta=0;
        if (son[k])
        {
            delta=dfs(son[k])^(1<<len[son[k]]);ans[k]=max(ans[k],ans[son[k]]);
            for (int i=p[k];i;i=edge[i].nxt)
            if (edge[i].to!=son[k])
            {
                ans[k]=max(ans[k],calc(edge[i].to,delta^(1<<len[edge[i].to]))-(deep[k]<<1));
                add(edge[i].to,delta^(1<<len[edge[i].to]),1);
            }
        }
        ans[k]=max(ans[k],f[delta]-deep[k]);
        for (int i=0;i<22;i++) ans[k]=max(ans[k],f[delta^(1<<i)]-deep[k]);
        update(delta,deep[k],1);
        return delta;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("741D.in","r",stdin);
        freopen("741D.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=2;i<=n;i++)
        fa[i]=read(),addedge(fa[i],i,getc()-'a');
        deep[1]=1;make(1);
        dfs(1);
        for (int i=1;i<=n;i++) printf("%d ",ans[i]);
        return 0;
    }
     
  • 相关阅读:
    mysql 提权总结
    CTF线下赛AWD套路小结
    url的三个js编码函数escape(),encodeURI(),encodeURIComponent()简介
    url的三个js编码函数escape(),encodeURI(),encodeURIComponent()简介
    使用httpclient必须知道的参数设置及代码写法、存在的风险
    使用httpclient必须知道的参数设置及代码写法、存在的风险
    HttpClient学习笔记
    HttpClient学习笔记
    HttpClient系统日志配置
    HttpClient系统日志配置
  • 原文地址:https://www.cnblogs.com/Gloid/p/10240860.html
Copyright © 2011-2022 走看看