树上差分
树上差分是我认为是LCA的一种应用方式,由于树的特性,我们在求解树上差分时是能从底向上求解,这样树上差分的适用范围有了一定的限制,例如我们在求解过程中只有子树和的统计才是有意义的,单纯统计一条边上的和是没有任何意义的,这是我们在更改时就只更改了从节点到LCA这一区间的值,对于从别的分治来的统计和,只能代表从这从这一分支向上传递的更改。
树上差分适用于这种问题——对树上的一段路径进行操作,并询问某个点或某条边被经过的次数,此时我们可以利用树上差分实现懒惰更改,并在最终求结果时,采用DFS一次遍历获得对所有点或者边更改的结果。
值的注意的是,对于点差分和边差分会有一些细微的区别。
点差分:
设将两点u,v之间路径上的所有点权增加x,o=LCA(u,v),o的父亲节点为p,则操作如下:
我们需要将u,v的值加x,将o的权值减x,将p的权值减x
操作前:
操作后:
边差分:
边差分与点差分有一些细微的不同,设将两点u,v之间路径上的所有变权增加x,o=LCA(u,v),o的父亲节点为p,则操作如下:
我们需要将u,v的值加x,将o的权值减2*x
还是以上图为例,这里求边的差分后的结果如图所示:
例题
//树上差分的模板题目
#include<bits/stdc++.h>
using namespace std;
//这里以tarjan算法辅助求解
const int N=100010;
//并查集
int arr[N];
int find(int x){
return x==arr[x]?x:arr[x]=find(arr[x]);
}
void merge(int x,int y){
x=find(x);
y=find