[复习资料]用到树上差分思想的一类题目
注:此处的树上差分可能和某些树上差分不太一样。
一次考试考了这样一道题目:
给出一棵有\(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\),那么这次查询的答案就是下面几项的累加:
即:
然后两个\(F\)的差值是固定的,所以可以预处理出来。
对于修改操作,相当于是给点到根路径上的所有点的权值加上一个每个点特定的数。
对于询问操作,相当于询问点到根路径上的所有点权值之和。
树剖即可。
例题:
首先,题目中的询问\(\sum_{i=l}^rdep[\operatorname{LCA}(i,z)]\)可以拆成两个询问:
考虑离线处理,排序后,一个一个点地加入,同时在加入的过程中询问。
上一题的弱化版?
k次方直接前缀和处理。
考试题:
给定一棵\(n\)个节点的树,边有长度,两种操作:修改边权;查询编号在\([L,R]\)之间的节点到节点\(x\)的路径的长度和。
记节点\(x\)到根的距离为\(dist_x\),那么:
所以题目相当于要求:
前两个很好维护,如果忽略修改,最后一个也可以排序后处理,所以关键是如何求出第三个式子。
前面的题目都没有带修改,考虑修改怎么做,由于修改只有一条边,所以可以直接找到线段树上那条边对应的节点修改就好了。
考虑将修改分块,然后在每个块内枚举1到\(n\)个点,然后再记录一个时间戳表示当前所在的询问编号,对于某个查询,直接将当前时间跳到当前询问的时间戳位置,边跳边修改边权。
若块的数量为\(B\),节点数和操作数相当,所以时间复杂度就是\(O(Bnlog_2^2n+n^2log_2n/B)\)。
处理后就是P4211 [LNOI2014]LCA的强制在线版本。
强制在线怎么写?考虑到离线时我们是一个一个点加的,加入一个点相当于是修改了一条链,在线段树上修改了\(log_2n\)个区间,考虑直接维护每个点加入后的信息,用可持久化线段树即可,空间复杂度\(O(nlog_2^2n)\)。
话说这样题目中这个树所有顶点的度数都小于或等于 3 这个条件就没用了欸
感觉这类差分可能算是一种套路吧,所以把它写了下来。
另:把分块那题和可持久化线段树那题套在一起,分块加主席树,又是一道好题(滑稽