动态点分治

…衆ロ難τιáo~ 提交于 2020-03-06 22:33:03

原理

动态点分治模板题。。说实话动态点分治有点像\(dp\)很灵活

回顾一下点分治,我们发现是利用重心的性质强行把暴力次数降低到了\(log\)次,动态点分治也差不多

由于我们需要修改,那么我们可以修改一次点分治一次,所以不能暴力点分治

考虑为什么点分治可以做到优秀的复杂度?因为重心的性质,每次递归访问的不是儿子而是子树的重心

那么我们可以根据这一点,建出点分树(按点分治递归顺序),在点分树上进行修改,由于点分树一定严格小于等于\(log\)层,所以复杂度可以有保证

例题

捉迷藏

每个点处开两个堆,一个堆用来维护向点分树下所有黑点的距离,另一个点用来标记删除(当然您直接写可删除堆也是可以的)

答案就是最大值和次大值拼起来啦~

不过这样做有可能选到的两个值其实来自原树的同一子树

所以我们再开一个堆,用来存放每个点所有原树上的儿子到改点的最大距离,选取答案的时候在这个堆里拼接

由于我们建出了点分树,所以更改的时候只需要改点分树上对应的链就可以了

开店

我们设\(siz[0]\)是子树内点个个数,\(siz[1]\)是子树内所有点到\(u\)的距离和,\(siz[2]\)的子树内点到\(f[u]\)的距离和

对于某个点\(u\)的答案为\(siz_1[u]+\sum siz_1[fa]-siz_2[p]+(siz_0[fa]-siz_0[p])*dis(fa,u)\)

我们每个点开个\(vector\),按权值排序,将三个\(siz\)做前缀和,二分可以求出对应区间

实际操作:跳点分树的时候,如果\(p\)\(fa\),那么\(ans-=siz_0[p]*dis(fa,u)+siz_2[p]\),如果当前点不是\(u\)\(ans+=siz0[p]*dis(p,u)\)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!