边分治和边分树

边分治就是,每次选择一条作为分治中心。然后把这条边断掉,在两个连通块内继续递归。

考虑将原树三度化,就是对于 u 的每条出边,新建一个点 w,连边 (u,w,0),(w,v,d),然后令 u=w。三度化后边分治的复杂度就是对的,为 O(nlogn)

边分治的好处是,每次只用考虑两个连通块的贡献。

因为边分树是二叉树并且树高为 O(logn),所以它可以和线段树一样可持久化或者合并。

进行边分治时,每个点有一棵二叉链(称这个为边分树链)和指向这个二叉树的某个结点,称这个为 au。初始时每棵二叉树都只有一个结点,au 就是唯一的那个结点。

然后每次分治,称在一个连通块内的点为黑点,另一个连通块内的点为白点,若当前点为黑点那么给 au 新建一个左儿子并且移动 au 到新建的这个点,否则新建右儿子。

这样边分治结束后每个点都维护了一棵独一无二的二叉链。有什么用呢?

如果两个点的二叉链在某个点上面都相同,那么表示这两个点在这些分治过程中都被分到了同一边。在某个点分叉说明从某个分治过程开始两个点不在同一个连通块了,两点间路径信息应该在这个点被统计。

每个点的边分树链是可以合并的,复杂度和线段树合并相同。所以我们可以在合并时统计一些信息。

需要可持久化的题可以不显式建出边分树链,依次插入时只需要提前记录一下一个点每次边分治被分到哪边即可。

1. P4565 [CTSC2018] 暴力写挂

考虑把其中一个 dep(lca(x,y)) 去掉。答案的式子可以化成:

dis(x,y)+dep(x)+dep(y)2dep(lca(x,y))2

考虑建出边分树链,然后在第二棵树上 dfs,在 lca 处边分树合并统计不同子树的信息。

边分树链上每个点维护一个 gu 表示子树内 dis(x,u)+dep(x) 的最大值。合并时,有 ansmax(glsu+grsv2d,glsv+grsu2d)。然后更新 gumax(gu,gv)

时空复杂度均为 O(nlogn)

2. CF757G Can Bash Save the Day?

考虑边分树可持久化,对于排列的一个前缀维护这些点的边分树链的并。查询直接跳边分树链即可。

边分树每个点维护子树点数和往左或右子树走的点到分治中心的距离之和。查询就跳一边计算另一边的贡献即可。

考虑交换排列的两个位置相当于重构两个前缀,直接重构即可。

时空复杂度均为 O((n+m)logn)

posted @   zltzlt  阅读(70)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示