题目链接:

Codeforces741D

题目大意:给出一棵树,根为$1$,每条边有一个$a-v$的小写字母,求每个点子树中的一条最长的简单路径使得这条路径上的边上的字母重排后是一个回文串。

显然如果一条路径上的字母重排后是回文串,那么最多有一个字母有奇数个。我们用$2^{22}$的一个二进制来记录有哪些字母有奇数个。剩下的只需要$dsu\ on\ tree$来求每个点的答案即可。对于每个点记录它到根的路径上的字母的二进制状态,显然位于一个点两个不同子树中的点的状态异或起来就是这两个点间路径的二进制状态。开一个桶存每种状态的最大深度然后在对于每个点求答案时依次遍历子树求出最大值即可。注意遍历轻儿子时要先用轻儿子子树中的点更新答案之后再将轻儿子子树中的点的信息加入桶中。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int cnt[5000000];
int head[500010];
int to[1000010];
int nex[1000010];
int size[500010];
int son[500010];
int val[500010];
int dep[500010];
int tot;
int n;
int x,y;
char ch[2];
int ans[500010];
int tag[500010];
void add(int x,int y)
{
nex[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void dfs(int x)
{
size[x]=1;
for(int i=head[x];i;i=nex[i])
{
dep[to[i]]=dep[x]+1;
val[to[i]]^=val[x];
dfs(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
{
son[x]=to[i];
}
}
}
void calc(int x,int anc)
{
ans[anc]=max(ans[anc],cnt[val[x]]+dep[x]-2*dep[anc]);
for(int i=0;i<22;i++)
{
ans[anc]=max(ans[anc],cnt[val[x]^(1<<i)]+dep[x]-2*dep[anc]);
}
for(int i=head[x];i;i=nex[i])
{
calc(to[i],anc);
}
}
void solve(int x,int opt)
{
if(opt==1)
{
cnt[val[x]]=max(dep[x],cnt[val[x]]);
}
else
{
cnt[val[x]]=-1<<30;
}
for(int i=head[x];i;i=nex[i])
{
solve(to[i],opt);
}
}
void dsu_on_tree(int x,int opt)
{
for(int i=head[x];i;i=nex[i])
{
if(to[i]!=son[x])
{
dsu_on_tree(to[i],0);
ans[x]=max(ans[x],ans[to[i]]);
}
}
if(son[x])
{
dsu_on_tree(son[x],1);
ans[x]=max(ans[x],ans[son[x]]);
}
cnt[val[x]]=max(cnt[val[x]],dep[x]);
ans[x]=max(ans[x],cnt[val[x]]-dep[x]);
for(int i=0;i<22;i++)
{
ans[x]=max(ans[x],cnt[val[x]^(1<<i)]-dep[x]);
}
for(int i=head[x];i;i=nex[i])
{
if(to[i]!=son[x])
{
calc(to[i],x);
solve(to[i],1);
}
}
if(!opt)
{
solve(x,-1);
}
}
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
scanf("%d%s",&x,ch);
add(x,i);
val[i]=1<<(ch[0]-'a');
}
dfs(1);
for(int i=0;i<=(1<<22);i++)
{
cnt[i]=-1<<30;
}
dsu_on_tree(1,1);
for(int i=1;i<=n;i++)
{
printf("%d ",ans[i]);
}
}

[Codeforces741D]Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths——dsu on tree的更多相关文章

  1. CF 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths [dsu on tree 类似点分治]

    D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths CF741D 题意: 一棵有根树,边上有字母a~v,求每个子树中最长的边,满 ...

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

    题目链接 \(Description\) 给定一棵树,每条边上有一个字符(a~v).对每个节点,求它的子树中一条最长的路径,满足 路径上所有边上的字符可以重新排列成一个回文串.输出其最长长度. \(n ...

  3. CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths——dsu on tree

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

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

    先说一下dsu算法. 例题:子树众数问题. 给出一棵树,每个点有点权,求每个子树中出现次数最多的数的出现次数. 树的节点数为n,\(n \leq 500000\) 这个数据范围,\(O(n \sqrt ...

  5. codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    题目链接:Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 第一次写\(dsu\ on\ tree\),来记录一下 \(dsu\ o ...

  6. [探究] dsu on tree,一类树上离线问题的做法

    dsu on tree. \(\rm 0x01\) 前言\(\&\)技术分析 \(\bold{dsu~on~tree}\),中文别称"树上启发式合并"(虽然我并不承认这种称 ...

  7. dsu on tree (树上启发式合并) 详解

    一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...

  8. codeforces741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  9. Codeforces 741 D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    D - Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 思路: 树上启发式合并 从根节点出发到每个位置的每个字符的奇偶性记为每个位 ...

随机推荐

  1. django 接受 ajax 传来的数组对象

    django 接受 ajax 传来的数组对象 发送:ajax 通过 POST 方式传来一个数组 接收:django 接受方式 array = request.POST.getlist(‘key[]’) ...

  2. *args **kwargs

    -----------耐得住寂寞,守得住芳华. # # -------------------------------[day10作业及默写]----------------------------- ...

  3. python学习第七篇——字典访问键与值

    此程序的目的在于,正确而简单的访问字典的键与值 favorite_languages={ 'jen':['python','c'], 'sarah':['c'], 'edward':['ruby',' ...

  4. freemarker根据模板生成word文件实现导出功能

    一.准备工作 1.创建一个03的word文档,动态的数据用占位符标志占位(如testname).然后另存为word2003的xml文件. 2.格式化xml文件,占位符的位置用${testname}代替 ...

  5. 如何命名Java变量

    如同酒店会给每个房间起个性化的名字一样,程序中的变量也需要用合理的名字进行管理--变量名! 需要注意,给酒店房间起名字时可以是数字,如“802”,也可以是有趣的名字,如“牡丹”.“美国总统”.“水帘洞 ...

  6. HDFS的命令

    .....Hdfs dfs -cat path hadoop fs - 等同 1 -ls 查看当前目录的文件和文件夹 2 -lsr 递归查看 3 -du 查看文件的大小 4-dus 查看文件夹中所有的 ...

  7. SQL UPDATE with INNER JOIN

    mysql - SQL UPDATE with INNER JOIN - Stack Overflowhttps://stackoverflow.com/questions/14491042/sql- ...

  8. PHP中友好的处理方式

    在使用PHP进行开发的时候,由于PHP是弱类型语言的特性,所以,偶尔会遇到一些意想不到的错误.规范我们的编程就变得尤为重要了.下面总结一下,我日常开发中的一些经验,可能有些地方不妥,还请多多斧正,指教 ...

  9. spark单击 搭建

    http://files.cnblogs.com/files/yxnyd/spark.zip

  10. 372.Definition of ListNode

    单项列表只能把后一个node中的所有数据copy到当前node再delete后一node. /** * Definition of ListNode * class ListNode { * publ ...