题目链接:

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. ASP.NET Core 判断请求是否为Ajax请求

    我们可以通过HTTP请求头来判断是否为Ajax请求,Ajax请求的request headers里都会有一个key为x-requested-with,值为XMLHttpRequest的header 所 ...

  2. SpringBoot整合定时任务异步任务

    1.定时任务 1.开启定时任务 @SpringBootApplication //开启定时任务 @EnableScheduling public class SpringBootDemoApplica ...

  3. 分布式系统消息中间件——RabbitMQ的使用进阶篇

    分布式系统消息中间件--RabbitMQ的使用进阶篇 前言     上一篇文章 (https://www.cnblogs.com/hunternet/p/9668851.html) 简单总结了分布式系 ...

  4. NLP是什么

    NLP是什么 而在计算机领域, NLP(Natural Language Processing),也就是人们常说的「自然语言处理」,就是研究如何让计算机读懂人类语言. 这包括,既要能让计算机理解自然语 ...

  5. Final Destination II -- 矩阵快速幂模板题

    求f[n]=f[n-1]+f[n-2]+f[n-3] 我们知道 f[n] f[n-1] f[n-2]         f[n-1]  f[n-2]  f[n-3]         1    1    ...

  6. 006-筛选分类排序搜索查找Filter-Classificatio-Sort-Search-Find-Seek-Locate

    006-筛选分类排序搜索查找Filter-Classificatio-Sort-Search-Find-Seek-Locate https://www.cnblogs.com/delphixx/p/1 ...

  7. Python学习第十四篇——类初步使用及面向对象思想

    class Restaurant(): def __init__(self,restaurant_name,cuisine_type): self.name = restaurant_name sel ...

  8. SQL UPDATE with INNER JOIN

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

  9. java kill thread command line

    multithreading - How do you kill a Thread in Java? - Stack Overflowhttps://stackoverflow.com/questio ...

  10. 获取环境变量,0x000000cb 操作系统找不到已输入的环境选项

    include "stdafx.h" #include <Windows.h> #include <iostream> #pragma warning(di ...