点分树学习笔记
关于点分树的一些理解
定义与性质
点分树,就是把点分治中的每一次的重心连起来,构成一棵树。
由于重心的性质,点分治最多有 层, 所以点分树的树高最多是
维护
一般维护两个值 和 , 表示这个点的子树对于这个点的贡献, 表示这个点的子树对于这个点的父亲的贡献。 用于对 进行容斥
每次修改时要在点分树上不断跳父亲,修改点分树上父亲的信息。
每次查询时要在点分树上不断跳父亲,询问点分树上父亲的信息,一般要用到容斥。用 容斥
具体看了题就理解了。
用途
一般用于静态条件下点分治可解,但是强制在线或带修的题。
维护树上点和点之间的关系, 树上的全局信息。
减少递归层数或限制一个点为根,计算过这个点的点对信息。
注意事项
点分树上的位置关系,距离关系,父子关系,祖孙关系,和原树上不同。
luogu6329震波
标签
点分治, 树状数组
思路
先考虑不带修的情况,那这就是道点分治裸题,但是这道题要求支持修改且强制在线。那么点分治就不能用了。
所以我们要用点分树。
对于每一个节点维护两棵树状数组 ( 存) , 维护距离当前点距离为 的点的价值和, 维护距离当前点的点分树上的父亲距离为 的点的价值和。
对于修改操作,改成增加,然后在点分树上不断跳父亲,修改 和 。
对于查询操作,在点分树上不断跳父亲,设询问点和父亲的距离为 , 那么对于每一层,把答案加上 用于去重,因为当前子树已经被计算过了。
维护两棵树状数组多麻烦啊,直接 或者 多方便,然而要注意 点分树上的位置关系,距离关系,父子关系,祖孙关系,和原树上不同。
所以这样做是错误的。
Code
[ZJOI2007]捉迷藏
标签
点分治,堆
思路
这道题实际上是要求动态维护树的直径。
大法好 ,考虑点分树解决。
像静态树直径一样,需要对于每个点维护从这个点伸入子树的最长链,和伸入不同子树的最长链和次长链,支持插入和删除,可以用可删堆实现。
对于每个点维护两个堆, 维护从这个点的子树伸向这个点的链, 维护从这个点的子树伸向这个点的点分树上的父亲的链。把这个点子节点的 的堆顶插入到一个堆,这个堆就是这个点的 .
维护一个 表示答案的堆,把 的堆顶和次堆顶加起来,插入一个堆,这个堆就是 , 因为是动态的,支持删除, 所以要用堆维护。
关于修改,没什么好说的,直接维护就好, 删除原来的答案,加入改变后的答案.
Code
[ZJOI2015]幻想乡战略游戏
标签
点分治
思路
一句话题面: 动态维护树的带权重心。
对于每一次修改,求一遍重心,复杂度显然是 。 发现这道题保证每个点的度数不超过 所以只要限制层数,那么就可以优化复杂度。考虑用点分治,使层数为 。
定义一个点的带权距离和表示树上所有点,到这个点的带权距离之和
根据重心的一些性质, 对于一个点,从它到重心,每个点的带权距离和一定是单调的。
所以从点分树的根开始,枚举它在原树中的每个子节点,考虑能不能更优,如果更优,递归到这个子节点所在联通块的重心。直到找不到更优解为止.
那么需要考虑如何判断是否更优,即如何查询一个点的带权距离和。 对于每个点,在点分树上维护三个值 , ,
: 这个点的子树中的点到它的带权距离和。
: 这个点的子树中的点到它点分树上的父亲的带权距离和。
: 这个点的子树的带权大小
修改很套路,查询暴力跳 , 一个点父亲对带权距离和的贡献就是