(树上启发式合并)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 1≤n≤5×105
Solution
字符串重排后是回文串,显然该字符串内最多只有一种字符出现奇数次,其余均出现偶数次。
很容易可以想到异或操作。
统计字符串是否只有一个字符出现奇数次,显然可以将字符表示为二进制数,每条边一个字符,我们就可以将边权设为 2 c h − ′ a ′ 2^{\\ ch-'a'} 2 ch−′a′ ,两条路的合并操作就可以 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 XORu⊕XORv 的二进制数中仅有一个 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 XORu⊕XORv=0 或者 XOR u ⊕ XOR v = 2 i \\text{XOR}_u\\oplus \\text{XOR}_v= 2^i XORu⊕XORv=2i
我们需要求的就是以 u u u 为根子树中的两点 x , y x,y x,y,满足 XOR x ⊕ XOR y = 0 \\text{XOR}_x\\oplus\\text{XOR}_y=0 XORx⊕XORy=0 或 XOR x ⊕ XOR y = 2 i \\text{XOR}_x\\oplus\\text{XOR}_y=2^i XORx⊕XORy=2i 的点对所有 ( x , y ) (x,y) (x,y) 中的最长长度。
对于以 u u u 为根的子树,树中可能存在的最长路径显然有三种:
- 不经过根
u
u
u
即最长路径在子树中 - 路径的一个端点就是根
u
u
u
即子树中的一点 v v v 与 根 u u u 构成的路径 - 经过根
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[XORu⊕2i]}−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