动态点分治
题目链接:bzoj 1095
题意:写 B z o j 的题意就是简单——题意见上……
题解:给定一棵树,每个点有黑白两种颜色,求树上最远两个黑点之间的距离。这道题用动态点分治和边分治都可以解决,在这里我采用的是动态点分治的做法(其实这两个东西大同小异)。首先介绍一下动态点分治的思想:和点分治一样,我们通过不断寻找树的重心,将树不断的分成一块一块的然后将问题分治成一个个子问题然后递归进入子树即可。对于这道题而言,子问题就转化为了如何在一个以重心为根的子树内寻找两个最远黑点之间的距离 X,X 显然等于对所有子树的 X 和所有黑点到根的最大值加最小值取 Max。所以我们对于一个重心需要维护两个堆(或Set),分别记录它的每个子树的最长链(堆①)和当前子树内的每个黑点到根的距离(堆②)。然后修改某个点的颜色就等于把它的 logn 个祖先的两个堆都进行修改维护——在堆中添加或删除元素。
我思故我在:我个人认为动态点分治有两个需要注意的事项:一是在维护当前子树的(堆②)时,我们记录的“距离”是每个点到当前子树的“原根”的距离而不是到当前子树的重心的距离;“原根”即为访问进入这个子树的那个点。还有就是对于两个堆的理解不够深入:当前子树的(堆②),它虽然关联到了当前的重心节点上但它实际上是在为当前重心节点的“父亲”节点服务的。所以在修改这个堆的时候应该与它父亲的(堆①)一并修改。这时就要注意一个小细节,在修改点 X 的颜色时应该注意先把 X 的(堆①)独自修改完后再进行上述操作。