zoukankan      html  css  js  c++  java
  • Codeforces Round #383 D

    传送门

    Description

    Arpa has a rooted tree (connected acyclic graph) consisting of n vertices. The vertices are numbered 1 through n, the vertex 1 is the root. There is a letter written on each edge of this tree. Mehrdad is a fan of Dokhtar-kosh things. He call a string Dokhtar-kosh, if we can shuffle the characters in string such that it becomes palindrome.

    He asks Arpa, for each vertex v, what is the length of the longest simple path in subtree of v that form a Dokhtar-kosh string.

    题意:一棵根为(1) 的树,每条边上有一个字符((a-v)(22)种)。 一条简单路径被称为(Dokhtar-kosh)当且仅当路径上的字符经过重新排序后可以变成一个回文串。 求每个子树中最长的(Dokhtar-kosh)路径的长度。

    Solution

    所求的路径其实就是只有(0/1)个字符出现奇数次的字符串

    发现最多只有(22)种字符,所以可以把一个点到根路径上字符的出现情况压成一个二进制数(val_i)

    一个数位(i)(1)表示路径上编号(i)的字符出现了奇数次

    所以一条路径合法等价于(val_a xor val_b=0 or 2^i)

    发现是静态的子树信息维护,可以采用(dsu on tree)

    每个点只计算以这个点为(LCA)的最长路径,可以一个一个子树合并进来

    维护一个(mxdep_i),表示(val_x=i)的最大的(dep_x)

    对于(dsu on tree)

    如果一个关于子树集合的询问满足

    1. 往一个集合里插入一个点是(O(1))

    2. 删除元素都是到空为止,且每个点的删除为(O(1))

    那么对于这个询问就可以做到(O(nlog_2n))

    因为每个点只会在轻边处被删除,因而最多被删除(O(log_2n))


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)>(b)?(b):(a))
    #define reg register
    using namespace std;
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MN=5e5+5;
    struct edge{int to,w,nex;}e[MN]; 
    int n,en,hr[MN];
    inline void ins(int x,int y,int w){e[++en]=(edge){y,w,hr[x]};hr[x]=en;}
    int val[MN],dep[MN],mx[MN],siz[MN];
    void dfs1(int x)
    {
        siz[x]=1;reg int i;
        for(i=hr[x];i;i=e[i].nex)
            val[e[i].to]=val[x]^(1<<e[i].w),
    		dep[e[i].to]=dep[x]+1,
    		dfs1(e[i].to),siz[x]+=siz[e[i].to],(siz[e[i].to]>siz[mx[x]])?mx[x]=e[i].to:0;
    }
    #define ri reg int i
    int cx,mx_dep[1<<22],ans[MN],Dec;
    void _cal(int x)
    {
    	if(mx_dep[val[x]]) cx=max(cx,dep[x]+mx_dep[val[x]]-Dec);
    	for(ri=0;i<22;++i)if(mx_dep[val[x]^(1<<i)])cx=max(cx,mx_dep[val[x]^(1<<i)]+dep[x]-Dec);
    }
    void _upd(int x){mx_dep[val[x]]=max(dep[x],mx_dep[val[x]]);}
    void cal(int x){_cal(x);for(ri=hr[x];i;i=e[i].nex)cal(e[i].to);}
    void upd(int x){_upd(x);for(ri=hr[x];i;i=e[i].nex)upd(e[i].to);}
    void clr(int x){mx_dep[val[x]]=0;for(ri=hr[x];i;i=e[i].nex)clr(e[i].to);}
    void dfs2(int x,bool kep=0)
    {
    	reg int i;
    	for(i=hr[x];i;i=e[i].nex) if(e[i].to!=mx[x]) dfs2(e[i].to);
        if(mx[x]) dfs2(mx[x],1);Dec=dep[x]<<1;
        for(i=hr[x];i;i=e[i].nex)cx=max(ans[e[i].to],cx);
        for(i=hr[x];i;i=e[i].nex)if(e[i].to^mx[x])cal(e[i].to),upd(e[i].to);
        _cal(x);_upd(x);ans[x]=cx;if(!kep)clr(x),cx=0;
    }
    int main()
    {
    	n=read();reg int i,x;
    	for(i=2;i<=n;++i)x=read(),ins(x,i,getchar()-'a');
        dfs1(1);dfs2(1);
        for(i=1;i<=n;++i) printf("%d ",ans[i]);
        return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    jquery插件课程2 放大镜、多文件上传和在线编辑器插件如何使用
    php课程 5-19 php数据结构函数和常用函数有哪些
    如何解决计算机显示文字乱码
    NSURLConnection使用
    UOJ #5. 【NOI2014】动物园 扩大KMP
    [ACM] n划分数m部分,它要求每一个部分,并采取了最大的产品(间隔DP)
    基于低压电力采集平台DW710C的基础开发
    eclipse 对齐行号在括号中显示和字体调整
    蜗牛—苍茫IT文章大学的路(十)
    国产与第三方库FFmpeg SDK
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10661183.html
Copyright © 2011-2022 走看看