(树上启发式合并)CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

Posted 繁凡さん

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(树上启发式合并)CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths相关的知识,希望对你有一定的参考价值。

整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


Weblink

https://www.luogu.com.cn/problem/CF741D

Problem

给定一棵以 1 1 1 为根的有根树,每条边的权值是 ['a','v'] 的一个字母。现对于每个树上结点 x x x ,求出结点 x x x 的子树的最长的一条 “回文” 路径的长度。“回文” 路径的含义是将路径上所有的字母取出,任意排列后可以组成一个回文串。

1 ≤ n ≤ 5 × 1 0 5 1\\le n\\le 5\\times 10^5 1n5×105

Solution

字符串重排后是回文串,显然该字符串内最多只有一种字符出现奇数次,其余均出现偶数次。

很容易可以想到异或操作。

统计字符串是否只有一个字符出现奇数次,显然可以将字符表示为二进制数,每条边一个字符,我们就可以将边权设为 2   c h − ′ a ′ 2^{\\ ch-'a'} 2 cha ,两条路的合并操作就可以 O ( 1 ) O(1) O(1) 使用 XOR \\text{XOR} XOR 来合并。我们可以根据一条路径上的异或和来判断是否是回文串。

显然对于树上两条路径之间的异或和有:

dis ( u , v ) = dis ( u , 1 ) ⊕ dis ( lca u , v , 1 ) ⊕ dis ( v , 1 ) ⊕ dis ( lca u , v , 1 ) = dis ( u , 1 ) ⊕ dis ( v , 1 ) \\begin{aligned} \\text{dis}(u,v)&=\\text{dis}(u,1)\\oplus \\text{dis}(\\text{lca}_{u,v},1)\\oplus \\text{dis}(v,1)\\oplus \\text{dis}(\\text{lca}_{u,v},1) \\\\ &=\\text{dis}(u,1)\\oplus \\text{dis}(v,1) \\end{aligned} dis(u,v)=dis(u,1)dis(lcau,v,1)dis(v,1)dis(lcau,v,1)=dis(u,1)dis(v,1)

因此,我们只需处理出每个点 u u u 到根结点 1 1 1 的路径权值的异或和 XOR u = dis ( u , 1 ) \\text{XOR}_u=\\text{dis}(u,1) XORu=dis(u,1),就可以 O ( 1 ) O(1) O(1) 计算出两点间的路径权值异或和。

显然一条路径合法(是回文串)当且仅当 XOR u ⊕ XOR v \\text{XOR}_u\\oplus \\text{XOR}_v XORuXORv 的二进制数中仅有一个 1 1 1 或一个都没有 ,即如下 23 23 23 种状态:

000...00  
100...00  
010...00 
 ......   
000...10   
000...01 

即合法路径 ( u , v ) (u,v) (u,v) XOR u ⊕ XOR v = 0 \\text{XOR}_u\\oplus \\text{XOR}_v = 0 XORuXORv=0 或者 XOR u ⊕ XOR v = 2 i \\text{XOR}_u\\oplus \\text{XOR}_v= 2^i XORuXORv=2i

我们需要求的就是以 u u u 为根子树中的两点 x , y x,y x,y,满足 XOR x ⊕ XOR y = 0 \\text{XOR}_x\\oplus\\text{XOR}_y=0 XORxXORy=0 XOR x ⊕ XOR y = 2 i \\text{XOR}_x\\oplus\\text{XOR}_y=2^i XORxXORy=2i 的点对所有 ( x , y ) (x,y) (x,y) 中的最长长度。

对于以 u u u 为根的子树,树中可能存在的最长路径显然有三种:

  1. 不经过根 u u u
    即最长路径在子树中
  2. 路径的一个端点就是根 u u u
    即子树中的一点 v v v 与 根 u u u 构成的路径
  3. 经过根 u u u ,两个端点在子树中
    即两个端点在子树中,路径经过了根 u u u

f[x] 表示当前子树中结点 v v v 到根结点 u u u 的路径的异或和等于 x x x 的结点 v v v 的最大深度。

对于第一种情况,显然答案就是 ans u = max ⁡ { ans u , ans v } \\text{ans}_u = \\max\\{\\text{ans}_u, \\text{ans}_v\\} ansu=max{ansu,ansv} v v v u u u 的子树中的一个结点。

对于第二种情况,显然答案就是 ans u = max ⁡ { ans u , max ⁡ { f [ XOR u ] , f [ XOR u ⊕ 2 i ] } − depth [ u ] } \\text{ans}_u = \\max\\{\\text{ans}_u, \\max\\{f[\\text{XOR}_u], f[\\text{XOR}_u\\oplus 2^i]\\} - \\text{depth}[u]\\} ansu=max{ansu,max{f[XORu],f[XORu2i]}depth[u]}

对于第三种情况,我们无法直接计算,此时显然可以直接进行树上启发式合并统计贡献。

即先计算轻儿子,回答询问之后,清空轻儿子的贡献 f i f_i fi,然后处理重儿子,保留重儿子的贡献 f i f_i fi,然后再计算一次剩余的轻儿子,保留贡献在数组 f i f_i fi 中,用于与上层合并。 此时经过根节点 u u u 的路径 ( x , u ) (x,u) (x,u)的长度显然为 max{f[XOR[x]], f[XOR[x] ^ (1 << i)]} - depth[u] + depth[x] - depth[u],即以 u u u 为根的出 x x x 子树的其他子树中与 XOR x \\text{XOR}_x XORx 异或和为 0 0 0 2 i 2^i 2i 的深度最大的结点 y y y 之间的距离。我们先更新答案 ans ,退出遍历以后再更新 f i f_i fi 数组,因为我们并不能自己匹配自己(

注意这里给的是边权,我们维护的时候需要再设一个数组 id 去区分开 ( u , v ) (u,v) (u,v) ( u , w ) (u,w) (u,w) ,比较麻烦。但它给定的边是 p i + 1 p_{i+1} pi+1 i + 1 i+1 i+1 连权值为 ch 的边,并保证 p i + 1 p_{i+1} pi+1 一定小于 i + 1 i+1 i+1 ,并且因为是树,没有环,所以我们可以只连单向边 ( p i + 1 , i + 1 ) (p_{i+1},i+1) (pi+1以上是关于(树上启发式合并)CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths的主要内容,如果未能解决你的问题,请参考以下文章

CF741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths

CF741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths

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

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

「CF741D」Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

CF600ELomset gelral 题解(树上启发式合并)