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++) 调了两个小时 这题要求维护& ...
随机推荐
- [Bzoj4517]排列技术(错排 + 预处理)
4517: [Sdoi2016]排列计数 Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 1508 Solved: 915[Submit][Statu ...
- Java实验--课上提到的随机数生成原理简单实现(不利用库生成随机数的简单算法)
对于随机数的实验,根据课程上的教程,有如下的公式: 对应的变量参数的说明: 其中对应的Mouduls变量对应的就是公式中a的值,在公式中的含义就是相当于要循环多少个数才重复的一个值. Multipli ...
- 转: ORACLE存储过程笔记2----运算符和表达式
运算符和表达式 关系运算 =等于<>,!=不等于<小于>大于<=小于等于>=大于等于 一般运算 +加-减*乘/除:=赋值号=>关系号. ...
- 使用datatables实现后台分页功能,减轻前端渲染压力
注意不同版本,参数名字及参数内容存在差异,具体可以参考https://datatables.net/upgrade/1.10-convert#Options 控制页面显示的参数:https://dat ...
- 避免使用vector<bool>
作为一个STL容器,vector<bool>仅仅有两点不正确. 首先.它不是一个STL容器. 其次,它并不存储bool.除此之外.一切正常. 一个对象要成为容器,就必须满足C++标准 ...
- SGU 321 知道了双端队列,
思路: 贪心. 每次删除最上面的边.. #include<utility> #include<iostream> #include<vector> #include ...
- POJ 1927 Area in Triangle(计算几何)
Area in Triangle 博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40707691 题目大意: 给你一个三角形的三 ...
- [学习笔记]渗透测试metasploit
1.渗透成功后,在meterpreter命令行,需要使用如下命令切换当前目录.更多信息,可以参考: meterpreter > pwd C:\ meterpreter > cd /&quo ...
- VS2013如何调用别人发布的WebService程序
这篇经验会告诉我们如何调用别人发布的WebService,并且需要注意的事项.现在就拿获取天气预报的接口举例,因为文中不允许有链接,所以在下文图中有WebService链接的地址. 工具/原料 VS2 ...
- 在 Vim 中优雅地查找和替换 vi【转】
本文转载自:http://harttle.land/2016/08/08/vim-search-in-file.html 总有人问我 Vim 中能不能查找,当然能!而且是超级强的查找! 这篇文章来详细 ...