【未完工题解】P3345 [ZJOI2015] 幻想乡战略游戏

P3345】题解

一:【题目描述】

  • 给定一个带点权和边权的树
  • 每次修改一个点的点权
  • 定义F[u]:dis(u,i)*nw[i]
  • 求F[u]最小值

二:【求解】

1.【暴力解法】

定义d[u]为u子树内点权和
钦定root暂时最优解,每次枚举其子节点v,每次变化量为(d[u]-2d[v])dis(u,v)

接下来证明如果d[u]-2d[v]<0,则带权重心一定在v子树中
我们考虑反证,如果d[u]-2
d[v]>0,则带权重心一定不在v子树中
引入v子树中节点w,满足d[w]<d[v]
因为d[u]>2d[v],则d[u]>2d[w],所以一定不在v子树中
那么如果d[u]-2*d[v]<0,则带权重心一定在v子树中

所以我们一直递归,直到所有v满足d[u]-2*d[v]>0,此时u为带权重心
但是如果树退化成一条链,则单次询问复杂度为O(n),显然TLE

2.【点分树解法】

考虑查询操作
如果树高度是logn的话,那么单次询问复杂度就是O(logn)的,可以通过此题
我们重构成点分树,在点分树上采取暴力解法
具体来说,钦定点分树root为最优解,每次枚举其在原树上的邻接点v,如果d[u]-2*d[v]<0,则跳到v所在的连通块的重心t上,这样可以保证复杂度正确(类似二分)
然后用类似换根的思路,修改t->u方向上t的邻接点w的d[w],离开的时候再复原

最后得到带权重心r,然后按照点分树容斥的套路f-g计算答案即可
修改操作的话,向上跳,修改祖宗节点的f,g就可以了
复杂度O(20qlog^2n)

不过对于查找重心,还有一种更简单但是常熟略大的思路,可以避免复杂的换根操作
钦定root为最优解,每次枚举其在原树上的邻接点v,直接点分树上查询计算F[v],在所有子节点的F[v]中取最小值,如果F[v]<F[w],跳到v所在连通块的重心
递归下去,就可以找到带权重心
复杂度O(20qlog^2n)

三:【代码】

(施工中...)

posted @ 2025-12-08 18:15  Ming3398  阅读(8)  评论(0)    收藏  举报