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

如果重排后能构成回文串,那么出现奇数次的字符最多一个。用一个22位二进制数表示每一个字母出现的次数的奇偶,把一个点到根节点的路径的异或值记为$s[u]$,那么就是在子树里找到两个点使其$s$值异或之后1的个数不超过1个,那么用dsu on tree就可以了

记得最后别忘了用儿子的答案更新自己的

 //minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#define inf -0x3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
inline char getch(){
char ch;while((ch=getc())>'z'||ch<'a');return ch;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
const int N=5e5+;
int head[N],Next[N<<],ver[N<<],tot;
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
int sz[N],d[N],son[N],s[N],ans[N],f[N*],a[N];char c[N];
int mx,n,bin[];
void dfs1(int u,int fa){
sz[u]=,d[u]=d[fa]+,s[u]=s[fa]^bin[a[u]];
for(int i=head[u];i;i=Next[i]){
int v=ver[i];dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
void calc(int rt,int u){
int now=s[u];cmax(mx,f[now]+d[u]-*d[rt]);
if((s[u]^s[rt])==) cmax(mx,d[u]-d[rt]);
for(int i=;i<;++i){
now=bin[i]^s[u];
cmax(mx,f[now]+d[u]-*d[rt]);
if((s[u]^s[rt])==bin[i]) cmax(mx,d[u]-d[rt]);
}
for(int i=head[u];i;i=Next[i]) calc(rt,ver[i]);
}
void update(int u,int k){
k?cmax(f[s[u]],d[u]):f[s[u]]=inf;
for(int i=head[u];i;i=Next[i]) update(ver[i],k);
}
void dfs2(int u,int k){
for(int i=head[u];i;i=Next[i])
if(ver[i]!=son[u]) dfs2(ver[i],);
if(son[u]) dfs2(son[u],);
mx=;int now=s[u];
cmax(mx,f[now]-d[u]);
for(int i=;i<;++i)
now=bin[i]^s[u],cmax(mx,f[now]-d[u]);
for(int i=head[u];i;i=Next[i])
if(ver[i]!=son[u]) calc(u,ver[i]),update(ver[i],);
ans[u]=mx;
if(!k){
for(int i=head[u];i;i=Next[i]) update(ver[i],);
f[s[u]]=inf;
}else cmax(f[s[u]],d[u]);
}
void spread(int u){
for(int i=head[u];i;i=Next[i]){
int v=ver[i];spread(v);
cmax(ans[u],ans[v]);
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read();
bin[]=;for(int i=;i<=;++i) bin[i]=bin[i-]<<;
for(int i=;i<=n;++i){
int u=read();c[i]=getch();
add(u,i),a[i]=c[i]-'a';
}
dfs1(,);
memset(f,0xef,sizeof(f));
dfs2(,);spread();
for(int i=;i<=n;++i) print(ans[i]);
return Ot(),;
}

CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)的更多相关文章

  1. Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...

  2. 【CodeForces】741 D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    [题意]给定n个点的树,每条边有一个小写字母a~v,求每棵子树内的最长回文路径,回文路径定义为路径上所有字母存在一种排列为回文串.n<=5*10^5. [算法]dsu on tree [题解]这 ...

  3. 【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    传送门 题意: 给出一颗以\(1\)为根的有根树,树边带有一个字符(\(a\)~\(v\))的信息. 输出对于每个结点,其子树内最长的简单路径并且满足边上的字符能够组成回文串. 思路: 显然最终的答案 ...

  4. 【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    题意:我们称一个字符串为周驿东串当且仅当重排它的字符可以组成一个回文串. 给出一个n个点的有根树,根为1,每条边上有一个从a到v的字符,求每个点的子树中所有简单路径可以组成的周驿东串中的最长长度. n ...

  5. CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)

    题目大意: 给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长 解题思路: 假定给你一个字符串,如何判定其经打乱能否 ...

  6. 【CF600E】Lomsat gelral(dsu on tree)

    [CF600E]Lomsat gelral(dsu on tree) 题面 洛谷 CF题面自己去找找吧. 题解 \(dsu\ on\ tree\)板子题 其实就是做子树询问的一个较快的方法. 对于子树 ...

  7. 【Luogu U41492】树上数颜色——树上启发式合并(dsu on tree)

    (这题在洛谷主站居然搜不到--还是在百度上偶然看到的) 题目描述 给一棵根为1的树,每次询问子树颜色种类数 输入输出格式 输入格式: 第一行一个整数n,表示树的结点数 接下来n-1行,每行一条边 接下 ...

  8. 树上启发式合并(dsu on tree)学习笔记

    有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...

  9. CF375D Tree and Queries(dsu on tree)

    思路 dsu on tree的板子,可惜人傻把 for(int i=fir[u];i;i=nxt[i]) 打成 for(int i=fir[u];i<=n;i++) 调了两个小时 这题要求维护& ...

随机推荐

  1. pycharm查看代码注释的方法,代码编写日志及作者信息等

    竟然在边栏有个右键的快捷键.annotate可以查看代码书写日期及作者 鼠标悬停可以看到更加详细的时间等信息 原理应该是利用git blame

  2. Client使用c#和odp.net连接server oracle

    http://blog.csdn.net/educast/article/details/6605655 Oracle.DataAccess.dll有2.X版本和4.X版本,VS2008开发用2.X ...

  3. Android双向seekbar(带刻度)

    ※效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/disso ...

  4. Android与设计模式——代理(Proxy)模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描写叙述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式 ...

  5. 【转】如何查看Oracle客户端版本及位数(Windows系统)

    一.方法一 查看oracle客户端版本:sqlplus -v 查看oracle客户端版本:sqlplus /nolog命令 Step 1:运行sqlplus /nolog命令,如果你服务器安装了多个客 ...

  6. 简单了解eMMC

    以下只是个人看法,有不妥之处,请批评指出. 参考资料:http://www.veryarm.com/1200.html 一.eMMC的发展 ROM→NorFlash→NandFlash→eMMC→UF ...

  7. FancyCoverFlow

    https://github.com/davidschreiber/FancyCoverFlow

  8. 算法导论—无向图的遍历(BFS+DFS,MATLAB)

    华电北风吹 天津大学认知计算与应用重点实验室 最后改动日期:2015/8/22 无向图的存储方式有邻接矩阵,邻接链表,稀疏矩阵等. 无向图主要包括双方面内容,图的遍历和寻找联通分量. 一.无向图的遍历 ...

  9. maven导入dom4j以及jaxen.jar报java.lang.UnsupportedOperationException:错误

    <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> & ...

  10. 解决Struts配置文件里无提示信息的问题

    (1)在struts2配置文件编写的时候.有可能无法提示所有信息,在配置文件里打个"<" 后,并没有不论什么的提示信息(使用快捷键Alt+/ 也不提示) 原因是下边的  &q ...