CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
一棵根为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)的更多相关文章
- Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...
- 【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 [题解]这 ...
- 【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
传送门 题意: 给出一颗以\(1\)为根的有根树,树边带有一个字符(\(a\)~\(v\))的信息. 输出对于每个结点,其子树内最长的简单路径并且满足边上的字符能够组成回文串. 思路: 显然最终的答案 ...
- 【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
题意:我们称一个字符串为周驿东串当且仅当重排它的字符可以组成一个回文串. 给出一个n个点的有根树,根为1,每条边上有一个从a到v的字符,求每个点的子树中所有简单路径可以组成的周驿东串中的最长长度. n ...
- CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)
题目大意: 给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长 解题思路: 假定给你一个字符串,如何判定其经打乱能否 ...
- 【CF600E】Lomsat gelral(dsu on tree)
[CF600E]Lomsat gelral(dsu on tree) 题面 洛谷 CF题面自己去找找吧. 题解 \(dsu\ on\ tree\)板子题 其实就是做子树询问的一个较快的方法. 对于子树 ...
- 【Luogu U41492】树上数颜色——树上启发式合并(dsu on tree)
(这题在洛谷主站居然搜不到--还是在百度上偶然看到的) 题目描述 给一棵根为1的树,每次询问子树颜色种类数 输入输出格式 输入格式: 第一行一个整数n,表示树的结点数 接下来n-1行,每行一条边 接下 ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
- 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++) 调了两个小时 这题要求维护& ...
随机推荐
- 用Google Analytics UTM标注社会化媒体分享流量来源
随着社会化媒体营销概念近两年的日益盛行,敢于吃螃蟹的营销工作者们展开了一些尝试,发现对社会化营销效果进行综合评估是一大难点,价值难以衡量.主要原因在于它的营销效果中混杂了直接的目标转化.品牌宣传.品牌 ...
- POJ 2348 Euclid's Game【博弈】
题目链接: http://poj.org/problem?id=2348 题意: 给定两个数,两个人每次从较大数中减去较小数的倍数,谁先得到0谁获胜,为谁赢? 分析: 令一种可能出现的整数对为(a,b ...
- HDU 2050 【dp】【简单数学】
题意: 中文. 思路: 不难发现数学规律是这样的,每次增加的划分区域的数量是每次增加的交点的数量再加一.然后就总结出了递推公式. #include<stdio.h> ]; int main ...
- javascript闭包诡异的问题
var funcs = []; for (var i = 0; i < 3; i++) { // let's create 3 functions funcs[i] = function() { ...
- HDU4763 Theme Section 【KMP】
Theme Section Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- 图像处理之基础---boxfiter
http://blog.sina.com.cn/s/blog_7221228801019yg2.html DSP6000图像位移与变形典型算法 http://blog.csdn.net/anson20 ...
- dm385的分辨率切换
建议用两个RSZ的输出来完成切换分辨率功能,帧率可以通过软件丢帧来实现. 两个SWMS增加了两个1080p60的读和写,对系统影响是比较大的. http://www.deyisupport.com/q ...
- linux下信息分屏显示
在字符界面下,经常遇到ls之后信息太长,只能看到最后一页的信息,这时就需要分屏显示了. 常用: ls | less 这样就可以分屏显示了,并可以用PgUp和PgDn来上下翻页. 也可以用: ls | ...
- 滑动窗体的最大值(STL的应用+剑指offer)
滑动窗体的最大值 參与人数:767时间限制:1秒空间限制:32768K 通过比例:21.61% 最佳记录:0 ms|8552K(来自 ) 题目描写叙述 给定一个数组和滑动窗体的大小.找出全部滑动窗体里 ...
- uboot中关于LCD的代码分析【转】
本文转载自:http://blog.csdn.net/oqqHuTu12345678/article/details/72236117 以下内容源于朱有鹏<物联网大讲坛>课程的学习,如有侵 ...