树链剖分总结

我这辈子都不会再写树链剖分了。


重链剖分

重链剖分就是将一棵树分成若干条链,每条链在线段树上映射成一个区间,对于每条链,其满足任意一点与其相连儿子,这个儿子是其子树中大小最大的,可用于解决路径操作。

这样划分有一个性质是从任意一点往上跳最多经过 \(\log_2 n\) 条不同的链,这样就可以在 $ O(n \ \log^2n )$ 的复杂度完成任意一点到其某个祖先的操作。

但如果操作是一个路径。

我们得先学会用重链剖分求 LCA。

重链剖分求 LCA

要求 \(x,y\) 两点的 LCA,我们先求出每个点所在的链的链首节点,记作 \(bl_i\)。当两点链首不同时,我们让链首深的往上跳到下一条链,直到两者链首相同,返回深度浅的即为 LCA。

重链剖分 路径操作

因为在求 LCA 中,每次所往上跳的都是一个在线段树上都是区间,直接维护就做完了。

长链剖分

顾名思义,就是每次的链都是能拿到的最长的,维护子树最深节点就能做,每次往上最多跳 \(\sqrt n\) 次。

长链剖分 k级祖先

我们维护每个链首长度为链长 \(d\) 向上向下 \(2d\) 个节点,假设要求 \(k\) 级祖先,就先找到 \(2^{i+1} > k \ge 2^i\)\(i\),用类似 倍增LCA 的方法找到 \(2^i\) 级祖先,我们问题就转换为求 \(k-2^i\) 级祖先,假设所在链首为 \(bl\),链长为 \(d\)

因为 \(k-2^i < 2^i \le d\),第二个小于等于是因为这是长链剖分,如果往上跳了 \(2^i\) 层所到的链还没有 \(2^i\) 长,纳闷这条链一定不是长链,往上跳 \(2^i\) 所经的链才是长链。

由于我们先前维护过链首上下的点,所以直接拿来用就做完了。

posted @ 2025-06-10 14:52  Air2011  阅读(31)  评论(2)    收藏  举报