树查询算法

树查询算法

本篇文章讲解树查询算法,树查询是指,查询某一条路径的信息,节点信息,子树信息等等。

树上倍增

我们定义 ancestor ( x , k ) \text{ancestor}(x,k) ancestor(x,k),为节点 x x x,向上走 k k k步的祖先节点,我们可以用树上倍增 O ( n log ⁡ n ) O(n \log n) O(nlogn)的时间内计算出来。

我们重新定义 ancestor ( x , k ) \text{ancestor}(x,k) ancestor(x,k)为节点 x x x,向上走 2 k 2^k 2k步的祖先节点。那么我们有DP公式:

ancestor ( x , k ) = ancestor ( ancestor ( x , k / 2 ) , k / 2 ) \text{ancestor}(x,k) = \text{ancestor}(\text{ancestor}(x,k / 2),k / 2) ancestor(x,k)=ancestor(ancestor(x,k/2),k/2)

则可以通过DFS遍历在在 O ( n log ⁡ n ) O(n \log n) O(nlogn)内计算出节点的全部倍增信息。

如果我们想找 k − t h k-th kth祖先,我们可以通过我们计算出的倍增数组进行二分逼近即可。详情查看博客树上倍增与LCA。

树遍历序数组

子树查询

我们对一颗树进行DFS遍历,并加入进入时间戳 d f n dfn dfn,那么对于子树 x x x,则其所有的孩子节点的 d f n dfn dfn必定是连续的。

例如子树 x x x的开始 d f n dfn dfn 1 1 1,结束 d f n dfn dfn 5 5 5,那么如果想求这个子树的和,我们直接对数组 1 − 5 1-5 15进行求和即可,这个过程可以使用树状数组,前缀和,线段树进行加速。

路径查询

我们定义 sum ( x ) \text{sum}(x) sum(x)为从根节点到节点 x x x路径上所有节点的和,如果我们更新一个节点的值,那么所有子树的 sum \text{sum} sum都要进行更新,因为子树的 d f n dfn dfn是连续的,我们可以通过树状数组,线段树进行更新。

树上差分

思想是将树看成是相交线段进行差分。分为点差分和边差分。通常需要结合LCA来实现。其实更推荐树链剖分,树链剖分可以很好的把LCA和线性结构组合在一起。

点差分

以统计一条路径上经过的点的次数为例子。

我们定义节点 x x x的差分变量:

diff x = val x − ∑ s ∈ son x val s \text{diff}_x = \text{val}_x - \sum_{s \in \text{son}_x} \text{val}_s diffx=valxssonxvals

我们有路径 δ ( s , t ) \delta(s,t) δ(s,t) l l l是LCA节点, f f f是LCA的父节点。

根据差分公式,我们有:

  • diff s \text{diff}_s diffs 1 1 1
  • diff t \text{diff}_t difft 1 1 1
  • diff l \text{diff}_l diffl 1 1 1
  • diff f \text{diff}_f difff 1 1 1
    点差分

做好差分之后,通过一遍自底向上的DFS即可统计所有节点的权值。

边差分

如果要统计经过边的数量,我们需要把边权转换为点权,这样更好处理。

我们知道,一个父边只对应一个子节点,那么我们就可以把父边的权值转移到子节点上,如果一条边被激活,那么他所连接的子节点同样被激活。

边差分

我们根据上述差分公式,可以得出:

  • diff s \text{diff}_s diffs 1 1 1
  • diff t \text{diff}_t difft 1 1 1
  • diff l \text{diff}_l diffl 2 2 2

同样做好差分之后,通过一遍自底向上的DFS即可统计所有节点的权值,即边的权值。

例题

P3258

树链剖分

重链剖分

树链剖分一般指重链剖分,详情参考树链剖分。

长链剖分

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值