感觉dsu on tree一定程度上还是与点分类似的。考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可。

  重排后可以变成回文串相当于出现奇数次的字母不超过1个。考虑dsu on tree,容易想到遍历时记录每种情况的最大深度,合并时类似点分的逐个计算贡献再合并即可。这里有个问题是得到某子树信息后,对于原来的根来说,这个信息还要再加上一个偏移量,但直接暴力显然复杂度就不对了。实际上维护信息过程中不断传递偏移量即可。

  一开始就发现了这个题只开了256M,于是机智的开了个map,悲惨的T掉了。然而题面里深藏不露的说了一句字母范围在a~v。这啥思博题啊。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,a[N],p[N],fa[N],size[N],deep[N],son[N],len[N],ans[N],t,f[<<];
struct data{int to,nxt;
}edge[N];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],len[y]=z,p[x]=t;}
void make(int k)
{
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
{
deep[edge[i].to]=deep[k]+;
make(edge[i].to);
size[k]+=size[edge[i].to];
if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to;
}
}
inline int rev(int x){return (<<)-^x;}
void update(int k,int x,int op)
{
if (op==) f[k]=max(f[k],x);
else f[k]=;
}
void add(int k,int x,int op)//对子树内统计信息时,偏移量为x
{
update(x,deep[k],op);
for (int i=p[k];i;i=edge[i].nxt)
add(edge[i].to,x^(<<len[edge[i].to]),op);
}
int calc(int k,int x)
{
int ans=f[x]+deep[k];
for (int i=;i<;i++) ans=max(ans,deep[k]+f[x^(<<i)]);
if (ans==deep[k]) ans=-N;
for (int i=p[k];i;i=edge[i].nxt)
ans=max(ans,calc(edge[i].to,x^(<<len[edge[i].to])));
return ans;
}
int dfs(int k)//获得的该子树信息的偏移量
{
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=son[k])
{
int delta=dfs(edge[i].to);
ans[k]=max(ans[k],ans[edge[i].to]);
add(edge[i].to,delta,-);
}
int delta=;
if (son[k])
{
delta=dfs(son[k])^(<<len[son[k]]);ans[k]=max(ans[k],ans[son[k]]);
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=son[k])
{
ans[k]=max(ans[k],calc(edge[i].to,delta^(<<len[edge[i].to]))-(deep[k]<<));
add(edge[i].to,delta^(<<len[edge[i].to]),);
}
}
ans[k]=max(ans[k],f[delta]-deep[k]);
for (int i=;i<;i++) ans[k]=max(ans[k],f[delta^(<<i)]-deep[k]);
update(delta,deep[k],);
return delta;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("741D.in","r",stdin);
freopen("741D.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++)
fa[i]=read(),addedge(fa[i],i,getc()-'a');
deep[]=;make();
dfs();
for (int i=;i<=n;i++) printf("%d ",ans[i]);
return ;
}

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

  1. 【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 [题解]这 ...

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

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

  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. codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)

    codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

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

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

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

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

  9. 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 ...

随机推荐

  1. lazy-load-img.js 源码 学习笔记及原理说明

    lazy-load-img.js? 1. 什么鬼? 一个轻量级的图片懒加载,我个人很是喜欢. 2. 有什么优势? 1.原生js开发,不依赖任何框架或库 2.支持将各种宽高不一致的图片,自动剪切成默认图 ...

  2. Python内存优化:Profile,slots,compact dict

    实际项目中,pythoner更加关注的是Python的性能问题,之前也写过一篇文章<Python性能优化>介绍Python性能优化的一些方法.而本文,关注的是Python的内存优化,一般说 ...

  3. SQL Server 中用DBCC Opentran语句查看未关闭的事务(转载)

    从SQL Server 2008开始,可以使用DBCC Opentran语句查看数据库中最早一个没有被关闭的事务,下面这篇文章讲述了如何使用DBCC Opentran语句. An Open trans ...

  4. DNS 协议

    DNS 入门 域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务.它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.DNS 使用 T ...

  5. Hive 实现 wordcount

    创建表: create table hive_wordcount(context string); load data local inpath '/home/hadoop/files/hellowo ...

  6. Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer' defined in class path resource

    我们在SpringBoot中用Jedis来访问Redis,其中Redis是采用集群(单机没有本篇文章的问题)的方式,在启用Redis的时候碰到如上问题. 错误的核心信息如下: Error creati ...

  7. HNOI2019 白兔之舞 dance

    HNOI2019 白兔之舞 dance 显然\(n=3\)就是\(n=1\)的扩展版本,先来看看\(n=1\)怎么做. 令\(W=w[1][1]\),显然答案是:\(ans_t=\sum_{i\mod ...

  8. [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [四] JSON数据解析

    [DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 场景模拟 接上一篇, JD SKU对应的店铺信息是异步加载 ...

  9. linux下core file size设置笔记

    现象说明:突然发现一台测试机器的java程序莫名其妙地没了,但是没有core dump!这就需要打开服务器的core文件生成的功能了,(即core dump文件),方便程序调试.1)core文件简介c ...

  10. 关于五子棋游戏java版

    一 题目简介:关于五子棋游戏 二 源码的github链接   https://github.com/marry1234/test/blob/master/五子棋游戏 三.所设计的模块测试用例.测试结果 ...