题目描述

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

思路

  不多的只能用树上启发式合并做的题。。。虽然算法很暴力,但是本题还是挺难想的。

  考虑一共只有22种不同的边权,我们要找的是经过重新排序后回文的路径,也就是说:为偶数时,必须有两两相同的;为奇数时,最多只能有一个多出来的。那么我们考虑状压,对第$i$种边权压成$1<<i-1$,这样我们找的路径就变成了:路径上所有边的异或和为0或者为22中状态的一种。(为什么要状压呢?随便举几个栗子就知道了)

  我们先处理出$d[i]表示i到根的异或和,那么任意路径(u,v)的异或和就是d[u] \oplus d[v],暴力统计时,我们先遍历一棵轻儿子,遍历完后再把轻儿子的贡献加入桶中,这样就可以做到让u变成此次暴力的lca,于是我们在now结点的子树中遍历到(u,v)时,先统计桶中有没有d[u],这样异或起来为0,再统计有没有和d[u]异或起来为2^i$的即可。

code

#include<bits/stdc++.h>
#define I inline
using namespace std;
const int N=;
const int inf=(<<)-;
int val[N],n;
struct node
{
int to,nxt,w;
}g[N];
int head[N],cnt; int d[N],sz[N],son[N],Son,buk[<<],now,dep[N],ans[N]; I int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} I void addedge(int u,int v,int w)
{
g[++cnt].nxt=head[u];
g[cnt].to=v;
g[cnt].w=w;
head[u]=cnt;
} I void get_son(int u)
{
sz[u]=;
for(int i=head[u];i;i=g[i].nxt)
{
int v=g[i].to,w=g[i].w;
d[v]=d[u]^w;dep[v]=dep[u]+;
get_son(v);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
} I void init(int u)
{
buk[d[u]]=-inf;
for(int i=head[u];i;i=g[i].nxt)init(g[i].to);
} I void get(int u)
{
ans[now]=max(ans[now],dep[u]+buk[d[u]]);
for(int i=;i<=;i++)ans[now]=max(ans[now],dep[u]+buk[(<<i)^d[u]]);
for(int i=head[u];i;i=g[i].nxt)
{
int v=g[i].to;get(v);
}
} I void add(int u)
{
buk[d[u]]=max(buk[d[u]],dep[u]);
for(int i=head[u];i;i=g[i].nxt)
{
int v=g[i].to;add(v);
}
} I void dfs(int u,bool op)
{
for(int i=head[u];i;i=g[i].nxt)
{
int v=g[i].to;
if(v==son[u])continue;
dfs(v,);
}
if(son[u])dfs(son[u],),Son=son[u];
now=u;
for(int i=head[u];i;i=g[i].nxt)
{
int v=g[i].to;
if(v==Son)continue;
get(v);add(v);
}
buk[d[u]]=max(buk[d[u]],dep[u]);
ans[u]=max(ans[u],buk[d[u]]+dep[u]);
for(int i=;i<=;i++)ans[u]=max(ans[u],dep[u]+buk[(<<i)^d[u]]);
ans[u]-=dep[u]<<;
for(int i=head[u];i;i=g[i].nxt)
{
int v=g[i].to;
ans[u]=max(ans[u],ans[v]);
}
if(!op)init(u);
} int main()
{
n=read();
memset(buk,,sizeof(buk));
for(int i=;i<=n;i++)
{
int x=read();
char ch=getchar();
while(ch<'a'||ch>'v')ch=getchar();
addedge(x,i,(<<(ch-'a')));
d[i]=<<(ch-'a');
}
get_son();
dfs(,);
for(int i=;i<=n;i++)printf("%d ",ans[i]);
}

CF741D 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. [Codeforces741D]Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths——dsu on tree

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

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

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

  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 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...

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

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

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

    CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 好像这个题只能Dsu On Tree? 有根树点分治 统计子树过x的 ...

  9. 【DSU on tree】【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    Description 给定一棵 \(n\) 个节点的树,每条边上有一个字符,字符集大小 \(22\),求每个节点的子树内最长的简单路径使得路径上的字符经过重排后构成回文串. Limitation \ ...

随机推荐

  1. mysql中间件分享(Mysql-prxoy,Atlas,DBProxy,Amoeba,cobar,TDDL)

    hello 各位小伙伴大家好,我是小栈君,这期我们分享关于mysql中间件的研究,也就是数据层的读写分离和负载均衡,希望能够在实际的应用中能够帮助到各位小伙伴. 下期我们将继续分享go语言的系列讲解, ...

  2. 各种xml配置文件(所含内部标签及顺序)的提示功能是真的人性化

    通过mybatis generator的配置文件来举例,其他配置文件(web.xml,mybatis,spring,springmvc等)同理 mybatis可以通过mybatis generator ...

  3. DCL语句

    DCL语句我们现在默认使用的都是root用户,超级管理员,拥有全部的权限.但是,一个公司里面的数据库服务器上面可能同时运行着很多个项目的数据库.所以,我们应该可以根据不同的项目建立不同的用户,分配不同 ...

  4. PMP涉及的几个工作系统

    PMP涉及的几个工作系统   工作系统作为事业环境因素,提高或限制项目管理的灵活性,并可能对项目结果产生积极或消极影响,包括项目管理系统.项目管理信息系统PMIS.配置管理系统.变更控制系统.合同变更 ...

  5. POJ 3020 Antenna Placement(二分图 匈牙利算法)

    题目网址:  http://poj.org/problem?id=3020 题意: 用椭圆形去覆盖给出所有环(即图上的小圆点),有两种类型的椭圆形,左右朝向和上下朝向的,一个椭圆形最多可以覆盖相邻的两 ...

  6. prefer-object-spread

    eslint报错: Use an object spread instead of `Object.assign` eg: `{ ...foo }`.(prefer-object-spread) 即: ...

  7. 18.Linux磁盘管理

    1.磁盘分区工具fdisk 1. 添加一块小于2TB的磁盘进行使用,步骤如下: 给虚拟机添加一块新的硬盘 使用fdisk进行分区 使用mkfs进行格式化 使用mount进行挂载 PS: 生产分区建议, ...

  8. Mysql高手系列 - 第27篇:mysql如何确保数据不丢失的?我们借鉴这种设计思想实现热点账户高并发设计及跨库转账问题

    Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 欢迎大家加我微信itsoku一起交流java.算法.数据库相关技术. 这是Mysql系列第27篇. 本篇文章我们先来 ...

  9. 使用 Hexo,Material Theme 以及 Github Pages 搭建个人博客

    准备条件 Node.js npm Git GitHub账号 开始搭建 hexo init Blog cd Blog npm install hexo-deployer-git --save npm i ...

  10. 百万年薪python之路 -- MySQL数据库之 Navicat工具和pymysql模块

    一. IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具,我们使用Navicat工具,这个工具本质上就是一个socket客户端,可视化的连接 ...