首页 > 其他分享 >浅说树上倍增(下)

浅说树上倍增(下)

时间:2025-01-20 16:03:39浏览次数:3  
标签:树上 deep 极值 深度 倍增 节点 dp

书接上文

树上倍增的具体实现

其实树上倍增大致可以分为三个步骤。

  1. dfs 预处理倍增数组设 d p [ x ] [ i ] dp[x][i] dp[x][i] 表示 x x x 点向上跳 2 i 2^i 2i 到达的点,初始值 d p [ x ] [ 0 ] dp[x][0] dp[x][0] 的值就为 x x x 的父亲节点的编号,在从根节点往下遍历的过程中,我们已经得到了该点上方所有点的倍增信息,可以得到状态转移方程:
    d p [ x ] [ i ] = d p [ d p [ x ] [ i − 1 ] [ i − 1 ] ; dp[x][i]=dp[dp[x][i-1][i-1]; dp[x][i]=dp[dp[x][i−1][i−1];
for (int j = 1; (1 << j) <= deep[x] - 1; j++) {
    dp[x][j] = dp[dp[x][j - 1]][j - 1];
}
  1. 调整两点深度对于深度不同的点,找最近公共祖先比较麻烦,所以我们先把两点的深度统一,即让深度较深的点跳到和深度较浅的点同一深度。具体跳跃方法可以参考差值的二进制数,比如 ( 10110 ) 2 (10110)_2 (10110)2​ ,就需要向上跳 2 1 , 2 2 , 2 4 2^1,2^2,2^4 21,22,24。换言之就是,找当前数值中最大的 2 k 2^k 2k 的数,找到后再减去这个数,然后继续找。
if (deep[x] < deep[y]) swap(x, y);
int index = __lg(deep[x] - deep[y]);
for (int i = index; i >= 0; i--) {
    if (deep[dp[x][i]] >= deep[y])x = dp[x][i];
    if (deep[x] == deep[y])break;
}
  1. 找最近公共祖先对于深度相同的两点 u u u , v v v ,他们的最近公共祖先可能是任意一个点,那么如何跳跃呢?我们观察这个两个点的 d p dp dp 数组可以发现,在 i i i 比较大的时候, d p [ u ] [ i ] = d p [ v ] [ i ] dp[u][i]=dp[v][i] dp[u][i]=dp[v][i] ,说明此时已经跳到了最近公共祖先上方,我们需要找到 d p [ u ] [ i ] ! = d p [ v ] [ i ] dp[u][i]!=dp[v][i] dp[u][i]!=dp[v][i]
    由于我们也不知道i的具体值,所以只能一个一个尝试,当树的深度最大为 1 0 5 10^5 105 时, i i i 的最大值为17即可, i i i 的值和数据范围 有关,一般不会超过20,如果发现 d p [ u ] [ i ] = = d p [ v ] [ i ] dp[u][i]==dp[v][i] dp[u][i]==dp[v][i],则不动,否则就同时跳到 d p [ x ] [ i ] dp[x][i] dp[x][i] 这个点,由于一个数一定对应一个二进制数,所以最终一定会跳到最近公共祖先。
for (int j = 18; j >= 0; j--) {
    if (dp[x][j] == dp[y][j]) continue;
    x = dp[x][j], y = dp[y][j];
}
return dp[x][0];

Tips:
对于边权为1的树,找到两点的最近公共祖先后,通过两点的深度差相减就能得到答案。对于边权不为1的树,虽然也是通过深度差相减得到答案,但是要注意,如果 deep 数组中存储的是该点到根节点的距离,那么在树上倍增第二步操作中,把两个点移动到相同深度的操作就是错误的,这里的深度指的是离根节点经过的节点数量,不是离根节点的距离,所以对于有边权的树,我们需要重新开一个距离数组 dis ,而不能直接修改 deep 数组,这两个在该代码中的作用是不一样的。

小结

树上倍增经常用来求解需要找最近公共祖先的问题,同样,对于序列问题,很多时候还需要求极值,树上倍增也可以用来处理树上路径的极值。处理办法和倍增求区间极值有一点区别,因为对于树上的每一个点,有唯一的父亲节点,但是儿子节点有很多,没有办法记录祖先节点向下找 2 k 2^k 2k 这个区间内的答案。
那么如何求解 u u u 点到最近公共祖先 x x x 之间的极值呢?先维护一个极值的倍增数组, m a x [ x ] [ i ] max[x][i] max[x][i] 表示 x x x 点到 x x x 向上移动 2 i 2^i 2i 这个区间的极值,在 u u u 点往上跳的过程中,同时更新极值即可。

标签:树上,deep,极值,深度,倍增,节点,dp
From: https://blog.csdn.net/CylMK/article/details/145264102

相关文章

  • 「NOIP2024」 树上查询
    update2024/12/28题目描述给定一棵树,每次询问区间\([l,r]\)的\[\max_{l\lel'\ler'\ler\landr'-l'+1\gek}\text{dep}_{\text{LCA*}(l',r')}\]引理证明先来证两个区间\(\text{LCA}\)的引理:对于\(\text{LCA}\{l,l+1,\dots......
  • 倍增问题
    前言在整理总结题解的时候突然发现倍增这一章竟然连题解都没有写过,直接晕厥T1:直接做T2:首先根据倍增思想,现预处理出开\(2^j\)次车,A/B先开车所到达的地点,和开的距离这样两种查询,都可以根据预处理的来倍增求出然后如何预处理呢?我们维护一个链表,链表开始是所有城市按照高度......
  • 倍增求lca
    非常重要的东西我甚至模拟赛都不打了来打笔记很简单啊,朴素lca是这样,两个节点,先令深度相等,然后一个一个往上跳直到跳到相同的位置则那个点为两点的lca但是令深度相等与往上跳的过程都要一个一个慢慢跳所以时间复杂度拉满了那么我们能以什么方式优化呢我们可以发现,每个数都可以......
  • 倍增算法【模板】
    原题链接https://www.luogu.com.cn/problem/P3865题解链接https://blog.csdn.net/WJTF2/article/details/136239183?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522423e6dee0d2c53e9645ecba193312fb3%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257......
  • 关于此题[ABC367E] Permute K times倍增思想的一些总结
    传送门第一次接触到倍增思想是用来求lca时,为了避免一层一层往上爬浪费时间复杂度。再后来就是区间DP中一小类问题或者是部分图上问题可以用倍增来优化。那么这道题其实可以看作图上问题来使用倍增优化。看到这道题的数据范围,K达到了\(10^{18}\)量级,这让我们不得不思考log级别往......
  • 树上启发式合并 DSU on Tree
    更新日志2025/01/07:开工。概念树上启发式合并,可以一定程度上减小合并操作的复杂度,或者保证正确性。思路对于每一个节点,我们都找出它的最重儿子,也就是子节点个数最多的儿子。如有多个,任选一个。首先统计其他轻儿子的答案(如果无需统计每个节点的答案,就不用了。)。下面正......
  • B. 树上的回忆 (memory) 题解
    \(dis(i,j)\)有两种转换方式,第一种是统计每条边被经过了多少次,第二种是变成\(\sum_{i=l}^{r}\sum_{j=l}^{r}dep(lca(i,j))\)。这里采用第二种(因为第一种寄了)。先考虑暴力,采取换根DP:把\([l,r]\)建一棵虚树。对于一个点\(x\)尝试计算\(\sum_{y}dep(lca(x,y))\)。\(y\)......
  • 二分 + 倍增 做题笔记
    一些关于二分和倍增的题,大体按照题目难度排序。1.CF1951HThanosSnap简要题意给定一个长为\(2^n\)的序列\(a_0,a_1,\cdots,a_{2^n-1}\),对所有\(t\in[1,n]\)求解如下问题:A和B两人在序列\(a\)上博弈,一共进行\(t\)轮操作。每轮操作的流程如下:A可以选......
  • DP优化——树上依赖性背包&P6326 Shopping
    P6326Shopping题意等价于要买一个连通块。首先如果我们能求出一个dp数组:\(f_{i,j}\)表示\(i\)子树内,有\(j\)元,一定要选\(i\),能得到的最大价值。那么\(f_{1,m}\)就是一定选根的答案。然后点分治即可。接下来就是怎么在合理的复杂度内求出dp数组。直接背包显然......
  • 智能升级:构建由Open AI驱动的实时交易系统,倍增收益潜力(附源代码)
    作者:老余捞鱼原创不易,转载请标明出处及原作者。写在前面的话:在金融科技的浪潮中,实时数据处理和智能决策的重要性日益凸显。在本文中,我将分享如何利用Kafka和LlamaIndex构建一套基于GPT-4o的高效人工智能实时交易系统。从下载和分析欧元/美元对的日线数据,到设置Kafka数......