BZOJ题目整理中的一些较难的题的题解

来源:互联网 发布:网络当前不存在家庭组 编辑:程序博客网 时间:2024/05/17 06:37

我觉得题解要详细。

1.ZJOI2015 幻想乡战略游戏
动态查询树的带权重心。

我们贪心地去想,如果当前点的儿子的dv比其余的节点的和还要大的话,答案一定在这个点的子树中。
然后显然我们要维护一个点分树,这棵树的深度一定是不超过log(n)的,接下来我们要考虑如何维护答案。

首先记录一下sumv,表示这个点在点分树中子树的dv,然后我们要记录这个点的子树到这个点的带权距离,这个很好更新,当我们修改一个点的时候,就沿着点分树向上走,然后更新他在点分树里的所有祖先,注意这里要用原树的距离更新,st表可以做到O(1),树剖的话复杂度多一个log
注意这里是点分树上的点的子树的带权距离和,虽然点分树和原树的父子关系不同,但是我们要维护的是整棵树的全部权值,所以说不必关心这个

我们再考虑如何计算每个点为重心时候的答案,用dis1直接记录子树的带权距离和, 然后我们沿着点分树向上走,首先要加上父节点和父节点的其他子树的距离,我们在更新时记录一下dis2,表示当前节点对父节点的答案贡献,然后在走到父节点的时候,答案加上dis1[fa[now]]dis2[now],然后再加上dis(now,fa[now])(sumv[fa[now]]sumv[now]),类似的树上分类讨论在动态点分治的题中很常见,也可以做一些树上数据结构的题。

向上修改是O(lgn)的,每次查询,我们沿着点分树向下走,计算出子节点作为重心的答案,取出比当前节点小的子节点的答案,向下找,由于点分树深度是O(logn)的,每次计算也是沿着点分树向上走一遍,所以每次查询的复杂度是O(lg2n)的。

代码到处都有,我就不放了,顺便吐槽一下这个题网上所有题解除了洛谷里的,代码风格我都看不懂233。百度上绝对没有比我写的详细的了所以说我好弱啊。

原创粉丝点击