[复习资料]用到树上差分思想的一类题目

注:此处的树上差分可能和某些树上差分不太一样。

一次考试考了这样一道题目:

给出一棵有\(n\)个节点的树,边有长度,点有两种颜色,一开始全是白色。

有两个操作:

修改操作:给出一个修改节点\(x\),将节点\(x\)染上黑色。

询问操作:给出一个询问节点\(x\),记所有黑点形成的集合为\(S\),求\(\sum_{y\in S}F(dist(\operatorname{LCA}(x,y)))\)

函数\(F\)定义为:\(F(x)=\sum_{i=1}^{x}i^k\)\(k\)为常数)。

其中\(1\le n\le 10^5,1\le k<P,0\le d\le 10^7\),时限\(2s\)

首先考虑如何得到答案,可以设从点\(x\)到根的路径经过的点依次为为\(x_1x_2x_3\dots x_y\),以它们为根的子树包含的黑点数量为\(a_1a_2a_3\dots a_y\),那么这次查询的答案就是下面几项的累加:

\[\begin{matrix}(a_1-0)F(dist_{x_1})\\(a_2-a_1)F(dist_{x_2})\\(a_3-a_2)F(dist_{x_3})\\ \vdots \\(a_y-a_{y-1})F(dist_{x_y})\end{matrix} \]

即:

\[\begin{matrix}a_1(F(dist_{x_1})-F(dist_{x_2}))\\a_2(F(dist_{x_2})-F(dist_{x_3}))\\ \vdots \\a_{y-1}(F(dist_{x_{y-1}})-F(dist_{x_y}))\\a_yF(dist_{x_y})\end{matrix} \]

然后两个\(F\)的差值是固定的,所以可以预处理出来。

对于修改操作,相当于是给点到根路径上的所有点的权值加上一个每个点特定的数。

对于询问操作,相当于询问点到根路径上的所有点权值之和。

树剖即可。


例题:


P4211 [LNOI2014]LCA

首先,题目中的询问\(\sum_{i=l}^rdep[\operatorname{LCA}(i,z)]\)可以拆成两个询问:

\[\sum_{i=1}^rdep[\operatorname{LCA}(i,z)]]-\sum_{i=1}^ldep[\operatorname{LCA}(i,z)]] \]

考虑离线处理,排序后,一个一个点地加入,同时在加入的过程中询问。


P5305 [GXOI/GZOI2019]旧词

上一题的弱化版?

k次方直接前缀和处理。


考试题:

给定一棵\(n\)个节点的树,边有长度,两种操作:修改边权;查询编号在\([L,R]\)之间的节点到节点\(x\)的路径的长度和。

\[n\le 50000,m\le 50000 \]

记节点\(x\)到根的距离为\(dist_x\),那么:

\[dis(u,v)=dist_u+dist_v-2dist_{\operatorname{LCA}(u,v)} \]

所以题目相当于要求:

\[(R-L+1)dist_x+\sum_{i=L}^Rdist_i-2\sum_{i=L}^{R}dist_{\operatorname{LCA}(u,v)} \]

前两个很好维护,如果忽略修改,最后一个也可以排序后处理,所以关键是如何求出第三个式子。

前面的题目都没有带修改,考虑修改怎么做,由于修改只有一条边,所以可以直接找到线段树上那条边对应的节点修改就好了。

考虑将修改分块,然后在每个块内枚举1到\(n\)个点,然后再记录一个时间戳表示当前所在的询问编号,对于某个查询,直接将当前时间跳到当前询问的时间戳位置,边跳边修改边权。

若块的数量为\(B\),节点数和操作数相当,所以时间复杂度就是\(O(Bnlog_2^2n+n^2log_2n/B)\)


P3241 [HNOI2015]开店

处理后就是P4211 [LNOI2014]LCA的强制在线版本。

强制在线怎么写?考虑到离线时我们是一个一个点加的,加入一个点相当于是修改了一条链,在线段树上修改了\(log_2n\)个区间,考虑直接维护每个点加入后的信息,用可持久化线段树即可,空间复杂度\(O(nlog_2^2n)\)

话说这样题目中这个树所有顶点的度数都小于或等于 3 这个条件就没用了欸


感觉这类差分可能算是一种套路吧,所以把它写了下来。

另:把分块那题和可持久化线段树那题套在一起,分块加主席树,又是一道好题(滑稽

posted @ 2021-01-04 21:17  xiaolilsq  阅读(164)  评论(0编辑  收藏  举报