动态点分治
Posted chdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态点分治相关的知识,希望对你有一定的参考价值。
一搬都是动态修改点权时我们使用动态点分治来保证时间复杂度.
这里说一下深刻的理解,首先建出点分树并不难我们只需要记一个fa甚至不需要记儿子就能维护出来这样的一棵树.
为什么要维护这样的一棵树下面根据例题具体论述:
1. 每次查询距离x距离不超过y的点权之和.
2. 点权有修改.
3. 强制在线.
如果光有1怎么办我们可以考虑一下换根,好像父亲的信息很难维护 不可行。
点分治?好像也不行,有一种做法是每个点维护主席树然后再暴力向上跳统计答案+去重。
其实如果没有强制在线这类似于三维数点问题,由于我学艺不精不会数点...
好像我们第二种思路就是复杂度高了一点,那么细致的讲下一下第二种思路吧.
每个点维护其子树内距离为d的点权和具体的我们可以使用线段树合并来保证复杂度.
考虑一下查询首先是在x处查询,x暴力跳父亲在父亲处查询此时注意容斥把x处y-1的距离减掉即可.
那么修改呢?同样是暴力修改点权但是好像这里空间开销过大 时间也是如此极其不优秀。
原因?我们可能要从一条链的底部跳到链的顶头很难受。
其实我们这样做的原因只是为了检索到所有的答案罢了.
所以可以用点分树这棵树来进行暴力检索答案的过程由于树非常的平衡logn 所以时间和空间上都是可以承受的。
具体的这能完全体现出检索答案的过程么?
在x点询问 我们直接在点分树中的x点所维护的主席树中查询,然后跳点分树的父亲,直到根。
正确性 这里先不考虑容斥,就是说其实它的思想是一个联通块一个联通块搞。当前我这个点所处的点分树的位置代表了以这个点为根时的状态。我们这个点跳父亲了之后表示的是这个联通块之外的点进行统计答案显然的是此时的意思是我们这个点跳出来统计答案而本身的联通块我们假设其消失,就是这样我们每次统计完一个联通块就假设其消失然后最终我们发现把所有的点都扫了一遍。正确性显然。
我们利用的不过是点分树log层这个优秀的性质。
那么你可能会发问我们在点分治的时候维护这个过程不就好了?带修呢?按照时间顺序一起跟询问放到vector里。
不得不说这样很难写我没写过不知道 但是这道题是强制在线的/cy
考虑容斥的事宜,我们发现在更新我们这个点的线段树也同时会更新点分树上父亲,如果两次查询显然有可能会重复。
但是重复的也只是我们这个点的集合里面的某些元素我们考虑把这些元素在我们这个点直接减掉。
也就是说我们需要另开一颗线段树表示和父亲里面重合的元素,距离自然还是到父亲的距离了。
这样这道题就做完了.
啊啊啊啊 卡了一下午常数啊 原因线段树里能不pushup就不要pushup 你手贱写pushup干啥啊直接在来的时候累加就行了.
啊啊啊啊 加register啊 求LCA的时候常数小一点别定义那么多变量什么的。真是人傻常数大。不过痛彻我的心扉。
再上一道例题深刻理解一下点分树:
树上有黑点和白点 求两个黑点之间的最长距离。
其实就是动态维护树的直径 线段树做这个要好一点 这里采用点分树.
这道题做法很多:点分树 线段树维护括号序列 线段树维护直径 LCT...
都很神仙,我都不会。这里简单分析一下点分树的做法:
首先我们要知道为什么使用点分树,显然静态的问题我们可以采用点分治来完成这个问题,因为待修改我们考虑点分树来进行动态修改。
我们要知道点分树上每个点要维护什么 显然要自己子树内合并的答案就行了要维护这个得知道自己子树内的最大和次大值。
但是出现问题了这两个值可能出自一个父亲和儿子他们真是距离并不是这样的。
我们很难进行合并两边的子树,但是 其点分树上的父亲可以 我们知道点都是由儿子调到父亲的 所以我们在其父亲处合并就可以保证是分属在两个不同的子树之中了。
我们发现所有叶子节点不可能对答案有贡献 所以我们只需要每个点维护其到其父亲的最大距离即可 在父亲处再维护一个所有儿子的最大值的堆就行了。
需要注意的是如果自己本身也是黑点那么还要多插入一个0.
值得一提的是因为每个点都可能被删除所以还需再维护一个伴生堆就行了...
以上是关于动态点分治的主要内容,如果未能解决你的问题,请参考以下文章