首页 > 其他 > 详细

Codeforces Round #383 D

时间:2019-04-06 13:17:00      阅读:183      评论:0      收藏:0      [点我收藏+]

传送门

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!

Codeforces Round #383 D

原文:https://www.cnblogs.com/PaperCloud/p/10661183.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!