浅谈 树上带权最长最短路径,决策包容性与点分树
最近学习了点分树相关的内容,也碰巧见识到了许多……树上路径问题(非负权),最长或是最短,有的可以用点分治(树)解决,有的可以用 线段树解决,有的需要深层次挖掘性质,就在这里做一个小小地总结了一些另类的方法。
1.树上带权最长路径
规律 :
带修最长路径问题往往可以通过 序转化为 在线段树上维护 最值的问题。
或者说,带权树直径……?
这个其实是在我思考…… luogu P7565 的一个愚蠢至极的做法的时候理解的。
引入:
给出一棵树边权为 ,有点权,定义 ,定义每个点 的树半径为 ,你需要支持修改点权,查询所有点树半径的最小值。
将半径问题转化为直接问题,可以证明半径最小值等于带权树直径的一半,于是维护树的直径,。
树上一条路径的长度可以被表示为 ,同时在 dfs 序上将路径拆分,(dfs序 求LCA)表示为 中最浅的点的父亲。
所以尝试将路径表示为 的形式,其中 表示父亲的深度。
或者说深度最浅的点这个限制的存在让我们难以维护,但是由于我们要求的是 ,所以对于一组 我们选择的 如果不是最浅的,那么这样一定不优,因为会让减的 变大,我们对这种并不正确的统计有包容性,这样是不影响答案的,所以可以直接维护 形如 的形式。
本题中就维护 ,就行了,可以支持单点修改。
维护的方式就是和 一样的,维护 ,这个东西显然可合并拼接。
*题目出处:CF1783 G.Weighed Tree Radius ,本题官方题解是线段是分治维护直径,常数大且不能在线。
例:
给你一棵树,带边权和点权,距离的定义 ,每次询问离一个点距离最大的点,支持修改边权和点权和加叶子。
加叶子就是个诈骗操作,离线了等于没有,
还是把路径拆成类似的形式,接下来我们要查的就是 序 在 前 后 分别查一下 和 的最大值就行了,然后修改点权是平凡的,修改边权其实就是给 做区间加,给 做一个区间加和一个单点修改。
题目来源:原创,感觉还行,虽然好像直接 LCT makeroot 模拟就行……?。
再举一个很蠢的例子,给一棵无根树对于每个 ,找出两个 且距离最远的不交子树。
先给树定个根,然后对于 有祖先关系的,直接 dfs 序上取 或者求 就行了,接下来考虑没祖先关系,这个时候就可以直接用 了,把点 从小到大加进去,然后就是类似刚刚的问题了,为了避免出现祖先关系,加入一个点之后把已经加入的祖先全部都设为不可用(正无穷)就行了,祖先一定在父亲被更新过了,所以只用更新父亲就行。
*题目出处:简化后的 JOISC 2021 Day3
2.树上带权最短路径
规律 :
带修最短路径问题可以考虑点分治(树),枚举分治中心作为路径上的点,将路径拆分成两半处理,这类问题往往可以转化为在点分树上子树内的最近点的查询。
引入:
如何给出一棵树(权值均非负),对于每个点 求 ?
这个问题并不困难,很容易想到用点分治解决,我们只需要对树进行质心分治,每次分治的时候处理所有过点 的路径,在计算时保留离分治中心最短及次短的路径就行了。
那么 动态修改 + 询问呢 ,例如修改一条边权或者点权,查询点权值。
这个时候就要使用点分树(动态点分治)了,将路径从点分树上的公共祖先拆成两部分 ,即枚举这条路径在点分治的哪一层被统计到的,然后接下来就要对于这个 ,求出 和 不在同一子树的 的距离的最小值,这是难以统计的,因为这个信息 不同于模板中的点权和,并没有可减性*。
*:点分树 在统计的时候往往要查询在 子树且不在 子树中的所有 的信息,这个形状在树上是很畸形难以维护的,往往需要利用信息的可减性或是包容性,我们稍后会谈到。
但是发现,我们可以不管和 不在同一子树这一限制,因为即使在不是 统计了,也不会影响答案,因为在不是 的点 统计,能够选择的 集合一定不会更大,因为在原树上的路径相当于多出了一段非负的长度 可以查询的集合也就更小了,我们把这种性质称作决策包容性。
决策包容性使得我们可以查询一个更完整的形态的集合,其中某些点一定不影响答案,这样在本题中,我们可以直接查询这整棵子树中最优秀的点,可以直接用数据结构维护。
点分树也使得一次修改 只需要考虑那 次分治时 到所选的分治中心所受到的影响,所以可以直接在 次中修改,在这道题中对边权的修改本质也是相同的,只需要拿线段树维护子树距离加减就行了,复杂度 。
*题目出处:PA2017 Banany,本题官方题解为树链剖分后维护启发式暴力维护轻子树信息,也有优雅的根号重构做法,值得一看。
例:
给出两棵树 ,定义两个点的距离 为标号 的点和标号 的点在两棵树上的距离和,对于每个点,求 距离最小的点,。
有一个部分分是 T2 是一条链。
这个部分分还是蛮显然,启发我们对 进行点分治,查询,把链上距离的绝对值拆开,查询 和 最近点就行了。
那么如果 T2 是一棵树呢?
我们显然不能 再枚举了,因为树上的路径关系是不能用简单的 左,右 来描述,常见的描述方式还是将路径从路径上一个点拆开,即点分治,我们考虑建出 T2 的点分树,然后查询时,枚举两个点在 点分树上的 LCA,然后在这 个点统计一下路径。
然后还是会有刚刚一样的问题:我们需要在 LCA 处统计,这很困难,因为我们需要要求 不在 处 的子树中,但是因为边权非负,那些不在 处被统计的点一定是不优的,路径一定变成了 的形式,这样统计到的点一定是不会影响答案的,于是我们可以直接查询 子树内和 最近的点就行了。
*题目出处:XX Open Cup Korea K.Wind of Change,本题官方做法为点分治+虚树。
于是我们可以把带有这种,查询在 子树且不在 子树中的所有 的信息,通过包容性或者可减性(模板题中查询 子树再减去 子树),转化为子树查询,这是一个形态完整的集合,往往可以用数据结构维护。
废话:
文化课好痛苦。
好像把我巨大的名字插进省队小小的名单里啊.jpg……?
本文已经结束了。本文作者:ღꦿ࿐(DeepSea),转载请注明原文链接:https://www.cnblogs.com/Dreamerkk/p/17428200.html,谢谢你的阅读或转载!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-05-24 【题解】CF603E | 半在线线段树分治