【算法】树上倍增 & LCA

相关链接

把相关链接放在最前面是因为,周赛遇到了几次,不会做。这才想起来学一下这个算法。

【力扣周赛】第 360 场周赛(⭐树上倍增)
【力扣周赛】第 361 场周赛(⭐树上倍增、LCA)

模板题目

1483. 树节点的第 K 个祖先

https://leetcode.cn/problems/kth-ancestor-of-a-tree-node/description/
在这里插入图片描述

提示:

1 <= k <= n <= 5 * 10^4
parent[0] == -1 表示编号为 0 的节点是根节点。
对于所有的 0 < i < n ,0 <= parent[i] < n 总成立
0 <= node < n
至多查询 5 * 10^4 次

class TreeAncestor {
    int[][] pa;

    // 使用原始数据将整个 pa 数组预处理出来
    public TreeAncestor(int n, int[] parent) {
        int m = 32 - Integer.numberOfLeadingZeros(n);   // n的二进制长度
        pa = new int[n][m];                 // 表示节点i的2^j个祖宗节点
        // 初始化dp数组,即填充每个节点的父亲节点
        for (int i = 0; i < n; ++i) {
            pa[i][0] = parent[i];
        }
        // 先枚举i,再枚举x
        // 相当于先算出所有爷爷节点,再算出所有爷爷的爷爷节点
        for (int i = 0; i < m - 1; i++) {
            for (int x = 0; x < n; ++x) {
                int p = pa[x][i];   // 取出x的第2^i个祖宗节点
                // x的第2^(i+1)个祖宗节点 等于 x的第2^i个祖宗节点的第2^i个祖宗节点
                pa[x][i + 1] = p < 0? -1: pa[p][i]; 
            }
        }
    }
    
    // 取出node节点的第k个祖宗节点
    public int getKthAncestor(int node, int k) {
        // 写法1 从低位到高位枚举
        // int m = 32 - Integer.numberOfLeadingZeros(k);   // k的二进制长度
        // for (int i = 0; i < m; ++i) {
        //     if ((k >> i & 1) == 1) {        // k的二进制当前位为1
        //         node = pa[node][i];
        //         if (node < 0) break;
        //     }
        // }
        // return node;

        // 写法2 不断去掉k末尾的1
        for (; k != 0 && node != -1; k &= k - 1) {
            node = pa[node][Integer.numberOfTrailingZeros(k)];
        }
        return node;
    }   
}

/**
 * Your TreeAncestor object will be instantiated and called as such:
 * TreeAncestor obj = new TreeAncestor(n, parent);
 * int param_1 = obj.getKthAncestor(node,k);
 */

最近公共祖先LCA的求法

两个节点 x 和 y,
先将 x 和 y 放在同一个深度上,即先让 y 跳 depth[y] - depth[x]。

当 x 和 y 在同一深度之后,如果 x = y,那么 x 就是 lca,否则 把 x 和 y 一起往上跳。
由于不知道 lca 的具体位置,因此从大到小枚举 i,尝试是否可以向上跳,直到 pa[x][i] == pa[y][i],循环结束之后,有 lca = pa[x][0]。

练习题目

2836. 在传球游戏中最大化函数值

https://leetcode.cn/problems/maximize-value-of-function-in-a-ball-passing-game/

2846. 边权重均等查询

https://leetcode.cn/problems/minimum-edge-weight-equilibrium-queries-in-a-tree/description/

扩展题目

把练习题目做明白就完了,咱先不扩展。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wei *

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值