dfs序和树状数组
点——子树类问题还算简单,这里就不展开讨论。下面主要针对Loj的板子题,谈谈我对dfs序的的见解。需要一些dfs序和差分的思想。
规定:
- 字母 x x x即可表示节点,亦可表示以该节点为根的子树。
- ( x , y ) (x,y) (x,y)表示 x x x到 y y y的路径。
- s u m [ i n [ x ] , o u t [ y ] ] sum[in[x], out[y]] sum[in[x],out[y]]表示按照dfs序对差分序列求和。
146
给一棵有根树,这棵树由编号为1…n 的n 个结点组成。根结点的编号为 r。每个结点都有一个权值,结点i 的权值为w[i] 。
接下来有 m组操作,操作分为三类:
1 a b x
,表示将「结点a 到结点 b的简单路径」上所有结点的权值都增加x ;2 a
,表示求结点 a的权值。3 a
,表示求 a的子树上所有结点的权值之和。
这个题还是用 d f s dfs dfs序,但是差分规则变了
先假设每一个点的权值都是0,那么对单点的数据更新将泛化到对单点构成的路径进行更新。因为全部赋值为0,那么无论做什么差分,其差分序列都是0。
引理一:
任何 单点修改可解释为路径修改。
引理二:
累计权值更改可以看作单次权值更改。
不证自明。
接着开始下定义:
定义一:
任何点的点权为 s u m [ i n [ i ] , o u t [ i ] ] sum[in[i], out[i]] sum[in[i],out[i]]。
这个定义决定了这个差分序列是树状有序的,而非一维有序。
推理一:
对该序列路径差分不会修改单点查询点权。
证明:
从全0序列开始,不妨设对路径 ( x , y ) (x,y) (x,y)进行路径差分。假设差分值为w,这时会有如下操作。
l c a = l c a ( u , v ) , f a = f a [ l c a ] . i n [ l c a ] − = w i n [ f a ] − = w i n [ x ] + = w i n [ y ] + = w lca = lca(u, v), fa = fa[lca].\\ in[lca]-=w \\ in[fa]-=w\\ in[x]+=w\\ in[y]+=w\\ lca=lca(u,v),fa=fa[lca].in[lca]−=win[fa]−=win[x]+=win[y]+=w
由 d f s dfs dfs序的性质可得, i n [ f a ] < i n [ x ] , i n [ f a ] < i n [ y ] in[fa] < in[x], in[fa] < in[y] in[fa]<in[x],in[fa]<in[y],且 i n [ l c a ] ≤ i n [ x ] , i n [ l c a ] ≤ i n [ y ] in[lca] \leq in[x], in[lca]\leq in[y] in[lca]≤in[x],in[lca]≤in[y]。
不妨设 i n [ x ] < i n [ y ] in[x] < in[y] in[x]<in[y]
- 假设在 i n [ l c a ] in[lca] in[lca]和 i n [ x ] in[x] in[x]之间夹了一子树 i i i,其和x相互独立,那么计算子树 i i i内任意一个节点的权值时,上述修改不会对其产生任何影响。
- 在第一条的假设下,令子树 i i i 包含 x x x,由 d f s dfs dfs序的性质可得, o u t [ i ] ≥ i n [ x ] out[i] \geq in[x] out[i]≥in[x],所以 o u t [ i ] ≥ o u t [ x ] ≥ i n [ x ] out[i]\geq out[x]\geq in[x] out[i]≥out[x]≥in[x]。因此上述修改一定影响到了 i i i的权值,使 i i i的权值增加w。
- 假设子树 i i i包含于 x x x,那么 o u t [ i ] ≥ i n [ i ] ≥ i n [ x ] out[i]\geq in[i]\geq in[x] out[i]≥in[i]≥in[x]。即完全不受影响。
- 假设子树 i i i包含 l c a lca lca。那么 o u t [ i ] ≥ o u t [ y ] ≥ o u t [ x ] ≥ i n [ l c a ] ≥ i n [ f a ] ≥ i n [ i ] out[i]\geq out[y]\geq out[