题目链接
题解
传说中的动态点分治,一直不敢碰
今日一会,感觉其实并不艰涩难懂
考虑没有修改,如果不用树形dp的话,就得点分治
对于每个重心,我们会考虑其分治的子树内所有点到它的距离,然后取所有不同子树中最大的两个相加来更新答案
如果带修改怎么办呢?
考虑一个点
\(u\)被修改了,会对哪些点产生影响。显然是包含它的分治子树之中
点分树
我们在点分治过程中,将每个重心与上一层分治重心相连,形成一棵树结构,叫做点分树
一个点被修改,仅影响其在点分树中所有祖先的答案
那么这样我们就可以维护了
对于每个点
\(u\),我们开两个堆分别储存一下信息:
堆
\(C\):以
\(C\)为根的分治子树中所有点到点分树中
\(u\)的父亲的距离
堆
\(B\):
\(u\)在点分树中所有儿子
\(C\)堆堆顶
对于全局开一个堆\(A\),储存所有堆\(B\)的最大值和次大值之和
那么堆\(A\)堆顶就是当前的答案
对于堆来说,插入是很方便的,但是删除就没那么简单,我们可以对每个堆再开一个堆,储存所有被删除的值,每次访问堆顶时,如果删除堆堆顶与当前堆顶相同,那么都\(pop\)掉,直到不相同位置
还要注意的就是堆间操作的顺序
我们要操作
\(C\),就得先将父亲
\(B\)堆中该
\(C\)堆堆顶
\(pop\)掉,操作完再加回去
同样,我们要操作
\(B\),也得先从
\(A\)中将对应贡献删除
感觉这题难点并不在动态点分治。。。而是在堆的维护吧。。。
#include #include #include #include #include #include #include