题目大意:
有一个 \(n\) 个点的带权树,有 \(q\) 次操作,分两种类型:
- 将一条边的权值改为 \(w\)。
- 查询 \(\sum_{i = l}^{r} dep_{LCA(i, x)}\)。
\(n, q \le 60000, 7s\),强制在线。
解题思路:
考虑 \(dep_{LCA(i,x)}\) 可以套路地拆成 \(dep_{i} + dep_{x} - 2 \times dep_{LCA(i, x)}\)。
那么我们对于 \(dep_{LCA(i,x)}\) 可以套路地拆成 \(i\) 与 \(x\) 到根地路径的交集的和。
但是由于有了修改,我们既要考虑标号上的连续段也要考虑 \(dfn\) 的连续段。
所以我们想到让分块来优化掉第一个维度,并在里面放个数据结构消掉 \(dfn\) 的维度,这是本题的第一个难点,也是解决二维的问题的比较有用的方法
那么由于我们查询的是点到路径上的交集,但他的深度跟边长有关,所以我们可以将 \(x -> fa\) 的这条边的边权改为 \(x\) 的点权。
那么我们变成了求一个点到根的被这个块内经过的次数乘点权的总和。
块内的点到根的路径上的点都会被更新一次。
所以一个点被经过了多少次等于他子树内的块内的节点个数。
由于我们每次修改相当于改一个点的点权,所以这是简单的。
我们现在的问题变成了动态更新点权,求点到根的点券总和。
这个树剖是很好做到 \(O(\log^2 n)\) 的,但是时间复杂度太高。
由于树剖是支持链加链查的,所以我们考虑舍弃功能来换取时间复杂度。
点到路径上的权值等于有哪些点的子树内有它,那么维护 \(dfn\) 即可。
那么 \(dep_{LCA}\) 求完了,那么我们还要块内维护求 \(dep_{x}\)。
但是这对于每个块来说只有单点查和整体查,所以即使他有 dfn 上的子树加也可以用树状数组方便地解决。
不过两个树状数组也能做区间加/查(((
散块也是简单的,直接暴力。
\(O(n \sqrt{n} \log n)\)
