Segment Tree Beats(势能线段树)

共 46 题
📑 题目列表 46 题
#
★★★

1. 1D / 1D DP 在单调栈与二分线段树混合的工程实现。

请说明 1D/1D 动态规划在单调栈与二分线段树混合下的工程实现?

  • 1D/1D DP 模型
  • 单调栈优化
  • 二分线段树

1D/1D DP 指状态一维、转移式依赖前驱状态的一维 DP。当转移需要在满足某种单调性(如区间最值、可行域收紧)的范围内取最优时,可用单调栈维护候选区间,配合二分线段树(或二分+线段树)定位转移点。例如:dp[i] = min(dp[j] + f(j,i)),若 f 满足四边形不等式/单调性,可用单调栈维护下凸包,用二分线段树快速查询最优 j。工程实现把"单调结构"与"线段树"结合,将 DP 从 O(n²) 优化到 O(n log n)。适合序列划分、区间覆盖类 DP。

1D/1D DP 的优化核心是"利用转移的单调性淘汰无用状态"。单调栈维护候选凸包,二分线段树在候选集中快速定位最优,二者结合把朴素 DP 复杂度大幅降低。

#
★★

2. 1D / 1D 动态规划在分治优化、Aliens Trick、Knuth 优化的取舍。

请说明 1D/1D 动态规划在分治优化、Aliens Trick、Knuth 优化之间的取舍?

  • 分治优化
  • Aliens Trick
  • Knuth 优化

这三者都是 1D/1D DP 的四边形不等式相关优化。分治优化(Divide and Conquer DP)适用于 opt[i] 单调、转移代价可分的情形,用分治批量计算最优决策点,O(n log n) 或 O(n log² n);Knuth 优化要求四边形不等式且单调,把决策点限制在 [opt[i-1], opt[i+1]],O(n²) 降为 O(n log n) 的近似;Aliens Trick 把"恰好 k 段"的约束转化为"每段代价"的拉格朗日惩罚,用二分惩罚系数求解,得到 O(n log C) 的带段数约束 DP。取舍:分治优化最通用、实现简单;Knuth 要求严格单调;Aliens Trick 适合带段数约束的最优化。

三者都依赖决策单调性,但形式不同:分治优化用单调决策点批量划分,Knuth 用决策点区间收紧,Aliens Trick 用惩罚系数把段数约束转光滑。根据单调性类型与段数约束选择。

#
★★

3. Quadtree 在图像处理与 GIS 索引的 O(n log n) 区域查询。

请说明 Quadtree(四叉树)在图像处理与 GIS 索引中的 O(n log n) 区域查询?

  • 四叉树空间划分
  • 区域查询
  • 复杂度

四叉树把空间递归均分为四象限,每节点覆盖一个区域。图像处理中,四叉树用于图像压缩(区域颜色一致则合并)、区域分割与空间查询;GIS 中用于点/区域的空间索引,区域查询(如矩形范围内所有点)沿树剪枝:若节点区域与查询矩形不相交则剪枝,完全包含则整块返回,部分相交则递归子树。复杂度 O(n log n) 或 O(log n + k)(k 为结果数),取决于树平衡与查询区域。四叉树适合均匀分布数据,但退化为 O(n) 在最坏情况。

四叉树用"相交剪枝 + 整块返回"加速区域查询。图像靠区域合并压缩,GIS 靠空间索引加速范围查询,复杂度依赖树的划分与剪枝效果。

#
★★

4. 李超线段树(Li Chao Tree)如何在 O(log n) 内插入直线并查询 x 处最大值,与凸包或单调栈的适用差异?

请说明李超线段树如何在 O(log n) 内插入直线并查询某 x 处的最大值,以及与凸包/单调栈优化 DP 的适用差异?

  • 李超线段树插入
  • x 处查询
  • 与凸包/单调栈差异

李超线段树维护一组直线,插入一条直线时,沿线段的 x 区间,若新直线在区间中点处优于当前直线则交换,并递归到新直线更优的半个区间,从而 O(log n) 插入;查询某 x 时,沿根到叶遍历所有区间的最优直线取最大值,O(log n)。它适合动态插入直线、在线查询任意 x 的最大值,常用于斜率优化 DP(dp 转移为 max 直线形式)。与凸包/单调栈差异:凸包/单调栈适合"插入斜率单调 + 查询 x 单调"的批量场景,实现简单但要求单调;李超树支持任意顺序插入与任意 x 查询,通用性更强,代价是 O(log n) 常数与实现复杂度。

李超树用"线段树节点存最优直线 + 中点决策交换"实现 O(log n) 插入与查询,不要求斜率或查询的单调性。凸包/单调栈在单调场景更快更简单,但李超树胜在通用。

// 李超线段树:插入直线 y = k*x + b,查询 x 处最大值
class LiChaoTree {
    double[] k, b; int n;
    LiChaoTree(int n) { this.n = n; k = new double[4*n]; b = new double[4*n];
        Arrays.fill(b, -Double.MAX_VALUE); }
    double f(int id, int x) { return k[id]*x + b[id]; }
    void addLine(int node, int l, int r, double nk, double nb) {
        int m = (l+r)/2;
        boolean leftBetter = f(node,l) < nk*l+nb;  // 新直线在左端点更优
        boolean midBetter = f(node,m) < nk*m+nb;   // 新直线在中点更优
        if (midBetter) { // 新直线在中点更优,交换到当前节点
            double ok=k[node], ob=b[node]; k[node]=nk; b[node]=nb; nk=ok; nb=ob;
        }
        if (l == r) return;
        // 失败者直线只可能在与胜者交叉的那一侧更优:两侧端点优劣不同则入左,否则入右
        if (leftBetter != midBetter) addLine(node*2, l, m, nk, nb);
        else addLine(node*2+1, m+1, r, nk, nb);
    }
    double query(int node, int l, int r, int x) {
        double res = f(node, x);
        if (l == r) return res;
        int m = (l+r)/2;
        if (x <= m) return Math.max(res, query(node*2, l, m, x));
        return Math.max(res, query(node*2+1, m+1, r, x));
    }
}
#
★★

5. 线段树分治在区间修改的离线加回溯的 O(n log² n) 推导。

请说明线段树分治在区间修改的离线加回溯场景中如何推导 O(n log² n) 复杂度?

  • 线段树分治
  • 区间操作
  • 复杂度推导

线段树分治把"区间有效、单点查询"的修改按时间/区间插入线段树节点:每个区间 [l,r] 被分解为 O(log n) 个线段树节点,修改加到这些节点上。离线 DFS 遍历线段树,进入节点时施加该节点的修改,回溯时撤销,叶子处回答查询。复杂度推导:每个区间修改落到 O(log n) 个节点,n 个修改共 O(n log n) 次节点插入;DFS 遍历所有节点共 O(n) 个节点,每节点施加/撤销需 O(log n)(如并查集),故总 O(n log² n)。该技术用于"修改在时间段内有效"的离线问题。

O(n log² n) 来自"区间 → O(log n) 节点 × 每节点操作 O(log n)"。线段树分治把"时间维度的区间生效"转化为"线段树层级的可回溯操作",是离线动态问题(如动态连通性)的经典解法。

#
★★

6. Klee's Algorithm 在区间并长度的 O(n log n) 工程实现。

请说明 Klee's Algorithm 求区间并长度的 O(n log n) 工程实现?

  • 区间并问题
  • 扫描线
  • 复杂度

Klee's Algorithm 求若干区间的并长度:先把所有区间端点收集并排序(离散化),用扫描线从左到右遍历端点,维护当前覆盖层数(在区间起点 +1、终点 -1),当覆盖层数 > 0 时,相邻端点间的长度计入并长度。排序端点 O(n log n),扫描 O(n),总 O(n log n)。相比朴素 O(n²) 两两判断,扫描线+覆盖计数高效且可扩展到区间并的周长等。工程上用差分思想,无需线段树即可处理静态区间并长度。

Klee's Algorithm 用"排序端点 + 扫描线计覆盖层数"把区间并转化为差分前缀,O(n log n)。关键是把"覆盖与否"变为端点处的层数增减,从而累加有效长度。

#
★★

7. 二维线段树在矩阵区域和与区域最值的 O(n log² n) 推导。

请说明二维线段树在矩阵区域和与区域最值中 O(n log² n) 复杂度的推导?

  • 二维线段树结构
  • 区域查询
  • 复杂度推导

二维线段树外层按 x 建线段树,每层节点内嵌一维 y 线段树(或按行合并)。区域查询(矩形 [x1,x2]×[y1,y2])先在外层分解 x 区间为 O(log n) 个节点,每个节点内再在 y 线段树 O(log n) 查询,总 O(log² n)。构建 O(n²) 或 O(n² log n) 取决于建树方式。对区域和/最值,单次查询 O(log² n)。相比暴力 O(n²) 扫描,二维线段树把区域查询优化为 O(log² n),但内存 O(n²) 较高,适合常数矩阵的静态区域查询。

二维线段树的 O(log² n) 来自"外层 x 的 O(log n) × 内层 y 的 O(log n)"两层分解。它把二维矩形查询转化为两层一维区间查询,是"线段树套线段树"的经典结构。

#
★★

8. 矩形覆盖在 union-find 与离散化的 O(n α(n)) 优化。

请说明矩形覆盖在 union-find 与离散化下的 O(n α(n)) 优化?

  • 矩形覆盖
  • 离散化
  • union-find 优化

矩形覆盖问题(统计被覆盖的格子数/区域)在离散化后,用扫描线每次处理一段 y 区间,需对区间内格子"逐个填充"。若用朴素逐个标记,可能 O(n²) 或 O(n·cell)。优化:用并查集(union-find)跳过头已被覆盖的格子,每个格子只被覆盖一次,后续覆盖 O(α(n)) 跳跃跳过,总复杂度 O(n α(n))。离散化把坐标缩到 O(n) 个关键点,配合并查集"下一个未覆盖位置"的跳转,避免重复填充。适用于矩形覆盖面积、被覆盖格子的染色问题。

并查集优化的核心是"用 find 跳到下一个未覆盖位置",保证每个格子只处理一次,摊还 O(α(n))。离散化缩小坐标规模,两者结合使矩形覆盖高效。

#
★★

9. 线段树分治在维护可撤销并查集与 segment tree 节点遍历。

请说明线段树分治中维护可撤销并查集与线段树节点遍历的实现?

  • 可撤销并查集
  • 线段树分治遍历
  • 回溯

线段树分治中,把"某时间段内生效的边/操作"插入线段树节点,DFS 遍历时进入节点施加其操作,退出时撤销。维护可撤销并查集:用按秩合并 + 操作栈记录每次合并的修改(父节点、秩),撤销时弹出栈恢复,保证 O(log n) 的合并与撤销。遍历时先施加节点操作,递归子树,再按逆序撤销(后进先出),撤退到叶子回答查询。可撤销并查集不能用路径压缩(破坏可撤销),只能按秩合并,保证 O(log n) 单次操作。

可撤销并查集的关键是"按秩合并 + 操作栈记录修改",撤销必须严格后进先出,因此不用路径压缩。线段树分治的 DFS 遍历保证"进入施加、退出撤销"的正确性。

#
★★

10. 线段树分治加可撤销并查集中回溯顺序必须严格后进先出,按秩合并如何支持撤销?

请说明线段树分治加可撤销并查集为何回溯顺序必须严格后进先出,以及按秩合并如何支持撤销?

  • 后进先出撤销
  • 按秩合并
  • 时间一致性

线段树分治的进入/退出必须严格对称:先施加的操作后撤销(后进先出),因为施加与撤销必须与 DFS 的递归顺序一致,否则中途状态被破坏,后续查询看到错误状态。可撤销并查集用按秩合并:每次 union 记录被修改的父指针与秩到栈中,撤销时弹出栈恢复先前状态(逆序执行)。由于按秩合并的树高 O(log n),撤销 O(log n);而路径压缩会修改大量父指针且破坏"仅记录本次修改"的可行性,故可撤销并查集不用路径压缩。后进先出保证撤销序列与施加序列严格镜像,维护状态一致性。

"后进先出"是回溯的必然要求:撤销必须按施加的逆序进行,才能回到原始状态。按秩合并保证单次修改可控、可记录,从而支持可撤销。

#
★★

11. 线段树套线段树在二维区间 K-th number 的 O(log² n) 推导。

请说明线段树套线段树在二维区间 K-th number 问题中的 O(log² n) 推导?

  • 树套树结构
  • K-th number
  • 复杂度

二维区间 K-th number(矩形内第 K 小)用线段树套平衡树/主席树:外层按值域建线段树,内层维护该值域区间内元素的坐标索引(如平衡树)。查询矩形第 K 小:外层二分值域,判断该值域内矩形中元素个数,若 ≥ K 缩小区间,否则调整。每次判断需在内层做二维计数 O(log² n),二分值域 O(log n),总 O(log³ n) 或配合外层线段树 O(log² n)。工程上常用"树状数组套主席树"或"线段树套平衡树"实现动态二维 K-th,复杂度 O(log² n) 每次更新/查询。

树套树把"值域"与"位置"两个维度分层,K-th 查询通过值域二分 + 内层计数。O(log² n) 来自两层 log 的组合,是动态二维排名的标准结构。

#

12. Boost Geometry R-tree 在空间索引的工程接口。

请说明 Boost Geometry 的 R-tree 在空间索引中的工程接口与使用?

  • R-tree 接口
  • 空间查询
  • 工程应用

Boost.Geometry 的 R-tree 提供 C++ 空间索引接口,支持插入/删除/查询空间对象(点、矩形、多边形)。常用构造参数(最大节点容量)、查询接口(query() 支持 bgi::nearest、bgi::intersects 等谓词)、迭代器遍历。工程上用于空间范围内查询、最近邻查询、空间连接。R-tree 基于 MBR 组织,从根节点按 MBR 与查询空间相交判断剪枝。Boost.Geometry 的 R-tree 封装了 STR 批量加载与动态插入,接口简洁,适合 C++ 空间系统。

Boost.Geometry R-tree 提供成熟的"空间对象索引"接口,封装 MBR 组织、剪枝查询与批量加载。工程上直接用 query 谓词实现范围与最近邻查询。

#

13. 树套树在矩形第 K 大与矩形不同元素数的离线持久化工程实现。

请说明树套树在矩形第 K 大与矩形不同元素数问题的离线持久化工程实现?

  • 树套树
  • 离线持久化
  • 矩形统计

求矩形第 K 大或矩形不同元素数,可用树套树(外层平衡树/线段树 + 内层坐标索引)配合离线持久化。离线持久化:把查询按 y 坐标排序,动态插入点(用树状数组/线段树维护 x 维信息),用"前缀可减性"把矩形和各维拆为差分查询。矩形不同元素数可用"last"位置法(维护每个元素上一次出现位置,矩形内不同元素 = 区间内 last 严格的阈值),配合树套树/主席树。工程上把二维问题转化为"按 y 排序 + 一维线段树 + 前缀差分",实现 O(n log² n)。

离线持久化把"二维矩形统计"转化为"按时间排序 + 动态一维结构 + 差分前缀"。不同元素数用 last 位置技巧,第 K 大用值域二分 + 计数,均依赖树套树的分层计数。

#

14. 树状数组套主席树在动态 K-th 的 O(log² n) 维护工程实现。

请说明树状数组套主席树在动态 K-th(带修改的区间第 K 小)中的 O(log² n) 维护工程实现?

  • 树状数组套主席树
  • 动态修改
  • 复杂度

带修改的区间第 K 小,用树状数组套主席树:外层树状数组按位置索引,每个节点维护一棵主席树(值域节点),支持点更新(修改时沿树状数组更新 O(log n) 个节点的主席树,每棵 O(log n),共 O(log² n))与区间查询(用树状数组定位 O(log n) 个位置,各主席树查询 O(log n),共 O(log² n))。这套结构把"静态主席树"扩展到支持点修改,实现动态区间 K-th 每次 O(log² n)。内存 O(n log n) 或 O((n+q) log n)。

树状数组套主席树把"位置"维度用树状数组支持 O(log n) 更新,把"值域"维度用主席树支持 O(log n) 计数,组合成 O(log² n) 的动态区间 K-th。是动态第 K 小的标准结构。

#

15. 树状数组套平衡树在动态区间排名与前驱后继查询工程实现。

请说明树状数组套平衡树在动态区间排名与前驱后继查询中的工程实现?

  • 树状数组套平衡树
  • 区间动态查询
  • 复杂度

动态区间排名/前驱后继查询需要用"位置 + 值域"两层结构。树状数组套平衡树:外层树状数组按位置分块,每个块内用平衡树维护该位置块的值。查询区间 [l,r] 内某值的排名:把 [l,r] 拆为 O(log n) 个块,每个块用平衡树统计小于 x 的个数,累加 O(log² n);前驱后继同理。点修改更新所属块的平衡树 O(log n)。相比主席树,树状数组套平衡树支持动态插入删除,但常数大。适合在线动态区间值域查询。

树状数组套平衡树用"位置分块 + 值域平衡树"实现动态区间排名与前驱后继,通过拆区间为 O(log n) 块并各块 O(log n) 查询,总 O(log² n)。

#

16. Segment Tree Beats 的势能分析中区间取 max/min/加这类操作为何总复杂度 O((n+q) log² n)?

请说明 Segment Tree Beats(势能线段树)对区间取 max/min/加等操作为何总复杂度 O((n+q) log² n)?

  • 势能函数
  • 次大值标记
  • 复杂度分析

Segment Tree Beats 维护最大(次大)值与计数,对区间取 min(chmin)操作:若 x ≥ 最大值直接返回;若 次大值 < x < 最大值,则只需更新最大值(打懒标记,O(1));否则递归。势能分析:定义势能为"节点最大值与次大值不同的次数"或"有效值的变化量",每次暴力递归会使势能下降,且势能总量有界。故总复杂度 O((n+q) log² n),其中 log n 来自递归深度、log n 来自势能界的每个节点累计。区间加会改变全局值但不破坏势能结构,取 max/min 的"区分度"保证势能单调下降。

势能线段树的复杂度来自"次大值/次小值区分度"这一势能:操作只在值域被"压平"时触发递归,势能单调下降且有界,故总复杂度亚 O(n log n)·每次。这是"均摊高效"的经典证明。

#

17. CF 813E 在线段树分治与持久化数据结构的工程实现。

请说明 CF 813E 题在线段树分治与持久化数据结构中的工程实现?

  • 问题建模
  • 线段树分治
  • 持久化

CF 813E 求每个区间内出现次数 ≤ k 的元素个数。朴素按位置用 last 位置法:维护每个元素前 k 次出现的位置,区间 [l,r] 内"合法"元素满足其第 k 次之前出现位置 < l。用持久化线段树(主席树)按位置建树,每个位置存"该位置元素第 k 次之前在更早位置"的累计,查询区间 [l,r] 用前缀可减性 O(log n)。也可用线段树分治按时间/位置离线处理。两种都依赖"把出现次数约束转化为 last 位置阈值",实现 O((n+q) log n)。

该题把"出现次数 ≤ k"转化为"第 k 次之前出现位置 < l"的阈值判断,用持久化线段树按位置前缀查询。线段树分治与持久化都是处理这类"离线区间统计"的框架。

#

18. CF 848C 在线段树分治的贡献拆解与离线 add 和 erase 工程实现。

请说明 CF 848C 在线段树分治中贡献拆解与离线 add/erase 的工程实现?

  • 贡献拆解
  • 线段树分治
  • 离线 add/erase

CF 848C 求区间内不同元素相邻出现位置差之和(或类似统计)。用"贡献拆解":把每个元素的贡献拆为相邻出现位置之差,某个元素在区间 [l,r] 的贡献由其出现位置序列决定。用线段树分治离线处理:把每个元素在查询区间内的出现位置按时间插入线段树节点,DFS 时 add/erase 维护贡献,叶子回答查询。离线 add/erase 保证每个元素的贡献在正确的时间段内有效,回溯时逆序恢复。复杂度 O((n+q) log² n)。

贡献拆解把"区间统计"分解为"每个元素相邻出现位置的贡献",线段树分治按时间维度的 add/erase 使贡献在有效区间内生效。这是"时间段内生效"类问题的标准做法。

#

19. CF 896E 在区间染色与区间减一与区间求和的工程实现。

请说明 CF 896E 在区间内大于 x 的元素减去 x、查询区间内等于 x 的个数等复合操作下的工程实现?

  • 复合操作
  • 懒标记
  • 势能优化

CF 896E 支持区间染色(赋相同值)、区间减一、区间求和。朴素懒标记线段树难处理"减一到零变零"与染色的结合。用势能线段树(Segment Tree Beats)或分块:维护区间最大值、次大值、最小值、最大值计数与和。区间减一:若最小值 > 0 则整段减一(懒标记);若最小值=0 且次小值>0,则对"最小值"做特殊处理;否则递归。染色用打标。区间求和用维护的和。势能保证总复杂度可控。工程上需精心设计懒标记的优先级与势能更新。

复合操作(染色+减一+求和)需要同时维护最小值/次小值/计数等多信息,用势能线段树处理"减一"的边界(最小值到零),配合懒标记高效回答求和。

#

20. KD-Tree 在 CGAL Kd-Tree 的静态与增量构建取舍。

请说明 KD-Tree 在 CGAL Kd-Tree 中的静态与增量构建取舍?

  • KD-Tree 构建
  • 静态 vs 增量
  • 工程取舍

KD-Tree 静态构建:按维度轮流取中位数分割,递归建树,O(n log n) 构建,查询高效(最近邻/范围);增量构建:逐个插入点,动态分裂节点,构建 O(n log n) 但树可能不平衡,查询退化。CGAL 的 Kd-Tree 提供静态构建(已知点集一次建树)与增量插入两种。取舍:静态构建平衡好、查询快,适合批量已知数据;增量构建支持动态插入但可能退化,适合流式数据。工程上按数据可获得性选择,静态场景优先用平衡构建。

静态构建用中位数分割保证平衡与查询性能,增量构建牺牲平衡换取动态性。取舍本质是"查询性能 vs 动态插入"的权衡,与数据的批量/流式特征相关。

#

21. KD-Tree 在 K 维最近邻查询的 O(2^d n^(1-1/d)) 推导。

请说明 KD-Tree 在 K 维最近邻(KNN)查询中 O(2^d n^(1-1/d)) 复杂度的推导?

  • KD-Tree 剪枝
  • 复杂度推导
  • 维数影响

KD-Tree 的 KNN 查询用"距离下界剪枝":沿树递归,若节点所在超平面到查询点的距离超过当前最优距离则剪枝该分支。平均复杂度 O(2^d n^(1-1/d)) 的推导基于"超矩形与查询球的相交概率":d 维空间中,树高 O(log n),但剪枝效率与维数 d 相关。n^(1-1/d) 表述了"每层访问的节点数随维数增长"——d 越大,剪枝越难,访问节点越多,当 d 接近 log n 时退化为 O(n)(线性扫描)。该复杂度反映维数灾难:高维时 KD-Tree 剪枝失效。

复杂度中的 2^d 与 n^(1-1/d) 都源于维数:高维超平面与查询球的相交概率增大,剪枝减少。这解释了为什么 KD-Tree 只在低维有效,高维退化为线性扫描。

#

22. Quadtree 与 KD-Tree 在 2D 区域查询的取舍。

请说明 Quadtree 与 KD-Tree 在二维区域查询中的取舍?

  • 空间划分方式
  • 区域查询
  • 取舍

Quadtree 把空间均分为四象限(固定划分),KD-Tree 按中位数交替分割(数据自适应)。区域查询:Quadtree 剪枝不相交象限、整块返回包含象限;KD-Tree 剪枝不相交分割区域。取舍:Quadtree 实现简单、适合均匀分布与图像/地图(固定网格),但数据非均匀时退化为深树;KD-Tree 数据自适应、平衡性好,适合非均匀点分布,但区域查询需按分割平面剪枝。工程上,Quadtree 适合网格/图像类空间,KD-Tree 适合点云/最近邻的高效索引。

Quadtree 固定划分简单但非均匀退化,KD-Tree 自适应划分平衡但按数据分布。取舍取决于数据分布与查询类型(区域 vs 最近邻)。

#

23. 二维线段树与持久化在矩阵历史版本的工程实现。

请说明二维线段树与持久化在矩阵历史版本查询中的工程实现?

  • 二维线段树
  • 持久化
  • 历史版本

查询矩阵的历史版本(如每个时间点的区域和/最值),可用持久化二维线段树:每个版本对应一个二维线段树根节点,修改时只复制路径上被修改的节点(O(log² n) 新节点),其余共享。查询某版本在任意矩形上的信息,沿该版本根节点 O(log² n) 查询。工程上,外层持久化线段树 + 内层数据结构,或块状持久化。内存 O(q log² n)。相比重建每个版本,持久化共享未变部分,实现版本化矩阵查询。

持久化二维线段树通过"修改路径复制"保留历史版本,共享未变节点,支持 O(log² n) 的历史版本区域查询。核心是"不可变 + 路径复制"。

#

24. 二维线段树在 KD-Tree 退化与四叉树的取舍。

请说明二维线段树在 KD-Tree 退化与四叉树场景下的取舍?

  • 二维线段树的稳定性
  • KD-Tree 退化
  • 四叉树取舍

二维线段树固定按 x/y 区间分割,不依赖数据分布,查询复杂度稳定 O(log² n),但构建与内存 O(n²) 或较高,适合静态密集矩阵。KD-Tree 按数据中位数分割,数据非均匀时可能退化(某些维度分割不平衡),查询退化到接近线性。四叉树固定四分,简单但非均匀也退化。取舍:二维线段树牺牲内存换取稳定查询,适合静态矩阵与精确区域查询;KD-Tree/四叉树更省内存、适合动态点集,但退化风险高。工程上按数据规模、静态/动态与内存约束选择。

二维线段树用"固定分裂"保证最坏 O(log² n),代价是内存;KD-Tree/四叉树用"数据自适应/固定分裂"省内存但可能退化。取舍是"稳定复杂度 vs 内存/动态性"。

#

25. 二维线段树在四叉树分块与扫描线的混合维护工程实现。

请说明二维线段树在四叉树分块与扫描线混合下的维护工程实现?

  • 四叉树分块
  • 扫描线
  • 混合维护

二维区域动态维护可结合四叉树分块与扫描线:用四叉树把空间分块,对每块维护聚合信息;扫描线按 x 或 y 顺序处理事件(如矩形边界),用分块结构在当前横截面维护区间信息。混合方案在需要"动态更新 + 区域统计"时,用分块(四叉树)降低更新代价,用扫描线处理事件顺序,适用于矩形覆盖、动态面积统计等。工程上,分块粒度需权衡更新与查询,扫描线保证事件按序处理。相比纯二维线段树,分块+扫描线更灵活、内存更省。

四叉树分块提供"局部更新"的灵活性,扫描线提供"事件顺序"的确定性,两者结合在动态矩形/区域问题上兼顾效率与内存。

#

26. 二维线段树在外部存储(External Memory)的工程实现。

请说明二维线段树在外部存储(External Memory)场景下的工程实现?

  • 外部存储模型
  • 磁盘 IO
  • 二维线段树适配

在外部存储(磁盘)模型下,二维线段树需考虑磁盘 IO 次数(B-tree 式扇出)。工程实现:用 B 树(B+ 树)替代内存线段树,每层按磁盘页组织,用高扇出节点减少 IO 跳数;二维情况用"主结构(按 x)+ 次结构(按 y,磁盘页)"或 R 树/网格索引。外部存储二维线段树的关键是"页面局部性":把空间相邻数据放在同一页,减少范围查询的磁盘访问。工程上常选 R-tree 或 B-tree 套结构,而非内存式二维线段树,因磁盘 IO 是主导成本。

外部存储的二维索引以"磁盘 IO 次数"为优化目标,用高扇出与页面局部性减少访问。二维线段树在内存模型高效,但磁盘场景需适配 B-tree/R-tree 结构。

#

27. 决策单调性在四边形不等式与 SMAWK 算法的判定工程实现。

请说明决策单调性在四边形不等式与 SMAWK 算法中的判定与工程实现?

  • 四边形不等式
  • 决策单调性
  • SMAWK 算法

四边形不等式(quadrangle inequality)是决策单调性的充分条件:若代价函数满足四边形不等式,则最优决策点单调。判定方法:验证或推导代价函数满足四边形不等式。决策单调性可用分治优化 O(n log n) 或 SMAWK 算法 O(n)(当转移为 Monge 矩阵、决策点单调时)。SMAWK 用"参数减少"技术,在 Monge 矩阵上快速求每行最优列,O(n+m)。工程实现:先验证四边形不等式,再选分治或 SMAWK,SMAWK 实现复杂但 O(n) 最优。适用于 DP 决策单调性优化。

四边形不等式是决策单调性的判定依据,SMAWK 在 Monge 矩阵上 O(n) 求最优决策。工程上先判定单调性,再按复杂度选择分治或 SMAWK。

#

28. 区间 chmin 与 chmax 在 max、second max、count 三元组工程实现。

请说明区间 chmin 与 chmax 操作在 max、second max、count 三元组上的工程实现?

  • chmin/chmax 定义
  • 三元组信息
  • 势能更新

区间 chmin(x) 把区间内所有 > x 的值改为 x,chmax(x) 把 < x 的值改为 x。为支持高效处理,每个节点维护 max、second max、count(最大值出现次数)三元组(chmin 用)以及 min、second min、count(chmax 用)。chmin 时:若 x ≥ max 直接返回;若 second max < x < max,则仅把最大值改为 x 并更新和(懒标记);否则递归。chmax 对称。三元组信息使"只改最大值"的 O(1) 分支可行,配合势能分析保证总复杂度。工程上需同时维护 max/min 两套三元组以支持双向 chmin/chmax。

三元组(最大/次大/计数)是 chmin 的必要信息:它让"只更新最大值并打标"成为 O(1) 分支,非此才递归。max 与 min 两套对称支持 chmin/chmax。

#

29. 区间 chmin 与 chmax 的势能 O(n log² n) 严格证明。

请说明区间 chmin 与 chmax 的势能 O(n log² n) 严格证明思路?

  • 势能函数设计
  • 均摊分析
  • 复杂度证明

严格证明区间 chmin/chmax 均摊 O(((n+q) log n) log n) 即 O((n+q) log² n):定义势能为"所有节点 (max - second max) 之差的 log 之和"或"节点上不同值的个数"。每次 chmin 若走"只改最大值"分支,势能减少(因为 max 与 second max 靠拢);若递归,则把势能减少映射到递归深度。可证明:每个节点的势能下降 O(log n) 次后变为稳定,且每次操作将势能分摊到 O(log n) 个递归节点,故总操作 O((n+q) log² n)。关键是用"最大值-次大值差异"作为势能,单调下降。

势能证明的核心是"最大-次大差异"为势能,chmin 使其单调下降且有界(每个值变化 O(log n) 次),把"所需递归"分摊到势能支出,得到 O((n+q) log² n)。

#

30. 扫描线与线段树在矩形面积并的 O(n log n) 工程实现。

请说明扫描线与线段树在矩形面积并中的 O(n log n) 工程实现?

  • 扫描线
  • 线段树覆盖计数
  • 复杂度

求矩形面积并:用扫描线按 x 坐标排序矩形的左右边(事件),用线段树维护当前 y 轴上的覆盖长度。每次处理事件时,更新该 x 区间内 y 方向的覆盖层数(+1/-1),用线段树维护"覆盖长度"(被覆盖的 y 总长度),累加"覆盖长度 × x 跨度"得到面积。y 坐标离散化,线段树节点维护覆盖层数与覆盖长度。排序事件 O(n log n),每事件线段树 O(log n),总 O(n log n)。相比扫描线 + 朴素维护,线段树高效处理覆盖层数更新。

扫描线把"二维面积并"转化为"一维覆盖长度的时间累加",线段树维护覆盖层数与总覆盖长度。离散化 y 使线段树规模 O(n),O(n log n) 完成。

#

31. 扫描线在 Segment Tree on Tree 的 O(n log² n) 路径查询。

请说明扫描线在 Segment Tree on Tree(树上的线段树)中的 O(n log² n) 路径查询?

  • 树上扫描线
  • 路径查询
  • 复杂度

树上路径查询(如"统计路径上满足条件的边/点")可通过扫描线 + 树剖分优化:把树路径用 HLD 拆为 O(log n) 条链区间,每条链区间映射到线段树;扫描线按某种顺序(如边权、深度)处理事件,配合线段树维护答案。O(n log² n) 来自"路径拆 O(log n) 链 × 线段树 O(log n)"。树上扫描线把"路径上的偏序统计"转化为"按排序顺序的事件 + 区间维护",适合离线 path 查询。工程上结合 HLD 与线段树,处理路径统计、路径最值等。

树上扫描线把"路径"经 HLD 拆为线性区间,再用线段树按事件顺序维护,O(log n) 链 × O(log n) 查询 = O(log² n)。是离线树路径查询的框架。

#

32. 扫描线在矩形周长并的下边长、上边长、左右边长统一推导。

请说明扫描线求矩形周长并时,下边长、上边长、左右边长的统一推导?

  • 周长并分解
  • 水平/垂直边
  • 扫描线维护

矩形周长并 = 所有水平边长度 + 所有垂直边长度。扫描线求水平边:按 y 排序矩形的上下边,扫描线维护 x 方向覆盖长度,每段水平边贡献 = 覆盖长度的变化量(新覆盖长度 - 旧覆盖长度),下边贡献 +、上边在用高度变化时计算。垂直边:按 x 排序左右边,扫描线维护 y 覆盖长度,垂直边贡献 = 覆盖层数变化 × 高度。统一推导:周长并(水平边和)= 扫描线更新前后覆盖长度的差加上边界;垂直边 = 覆盖层数非零的 y 段长度。工程上分别用两次扫描线(水平/垂直)或一次扫描线同时维护。

周长并分解为水平边 + 垂直边:水平边 = 覆盖长度变化量,垂直边 = 覆盖层数非零段的长度。扫描线用覆盖长度与层数分别维护两类边,统一累加得周长。

#

33. 洛谷 P6242 在区间取最值与区间求和与区间历史和的复合操作。

请说明洛谷 P6242 在区间取最值、区间求和、区间历史和复合操作下的工程实现?

  • 复合操作
  • 历史和
  • 势能线段树

洛谷 P6242 支持区间取最值(chmin/chmax)、区间加、区间求和、区间历史最大值等复杂操作。工程实现用势能线段树(Segment Tree Beats):维护 max/second max/count、min/second min/count、sum 以及 lazy 标记;同时维护"历史最大值"(历史版本中的最大和值)需要额外的历史标记与历史信息。取最值用三元组分支,加用懒标记,历史和用"历史最大懒标记"记录。操作复合通过多套懒标记的优先级处理,复杂度 O((n+q) log² n)。实现复杂,需严格管理标记顺序。

P6242 是势能线段树的综合题,同时处理取最值、求和、历史和的复合操作。多套懒标记(当前/历史、max/min)与历史和传播是核心难点,复杂度靠势能保证。

#

34. 矩形面积并的三维拓展在体积并的工程实现。

请说明矩形面积并的三维拓展(体积并)的工程实现?

  • 三维体积并
  • 扫描线维度扩展
  • 复杂度

三维体积并(长方体并)把扫描线从二维扩展到三维:先按 z 平面扫描,对每个 z 区间用"二维面积并"(扫描线 + 线段树)计算横截面面积,面积 × z 厚度累加得体积。复杂度倍增:二维面积并 O(n log n),三维体积并 O(n² log n)(外层 z 扫描 O(n) × 内层面积并 O(n log n))。工程上需维护三维覆盖层数,用线段树套线段树或分块。三维问题比二维复杂得多,工程上常用离散化 + 分段扫描 + 内层数据结构。

体积并是面积并的维度扩展:外层多一层 z 扫描,内层仍用面积并(扫描线+线段树)。复杂度随维度线性推高,体现"维度×复杂度"的累加。

#

35. 离线与在线混合的线段树维护 DP 在分治 FFT 配合工程实现。

请说明离线与在线混合的线段树维护 DP 在分治 FFT 配合下的工程实现?

  • 线段树维护 DP
  • 分治 FFT
  • 生成函数

某些 DP 转移形如卷积(生成函数),用分治 FFT(CDQ 分治 + FFT)优化:分治统计跨分治界的贡献,用 FFT 快速卷积,O(n log² n)。线段树维护 DP 用于"在线 + 离线"混合:把 DP 的转移按结构组织到线段树节点,离线预处理转移(用 FFT),在线查询时沿线段树快速求值。工程上,分治 FFT 处理卷积型 DP 的转移,线段树处理"区间/时间维度的结构",两者结合优化有组合结构的 DP。复杂度 O(n log² n)。

分治 FFT 用分治 + 卷积加速 DP 转移,线段树提供结构化的区间组织。两者结合用于"转移可卷积 + 区间结构化"的 DP,是生成函数/卷积 DP 的优化。

#

36. 线段树分治在动态图连通性 offline 的工程实现。

请说明线段树分治在动态图连通性(offline)问题中的工程实现?

  • 动态图连通性
  • 线段树分治
  • 可撤销并查集

动态图连通性 offline 问题:边在时间区间内存在,查询时刻图的连通性。用线段树分治:把每条边的存在时间区间插入线段树节点,DFS 遍历时施加节点上的边(可撤销并查集 union),回答叶子时刻的连通性查询,回溯时撤销。Edge 在有效时间区间内生效,保证每个时刻的状态正确。复杂度 O((n+m+q) log q log n)(边 O(log q) 次插入 × 并查集 O(log n))。线段树分治把"时间维度的动态边"转化为"线段树节点的可撤销集合",是离线动态连通性的标准解法。

线段树分治 + 可撤销并查集把"时间维度的动态连通性"转化为"树节点施加/撤销边",离线逐时刻回答。复杂度由"边插入 O(log q) × 并查集 O(log n)"决定。

#

37. 线段树分治在图论二分性约束的离线判定工程实现。

请说明线段树分治在图论二分性约束的离线判定中的工程实现?

  • 二分性判定
  • 可撤销并查集
  • 离线

判定图在时间维度上是否始终保持二分(或某时刻是否二分性成立),用线段树分治 + 可撤销并查集:把边按时间区间插入线段树节点,DFS 时施加边,用"带权并查集"(维护每个点到根的奇偶性)判定二分性,回答叶子时刻的查询,回溯撤销。若某时刻出现奇环则非二分。带权可撤销并查集支持合并与奇偶判断,回溯时逆序恢复。复杂度 O((m+q) log q log n)。线段树分治把"时间维度的二分性约束"转化为"线段树节点上的可撤销图构建"。

二分性判定用带权并查集(奇偶),配合线段树分治处理时间维度的动态边,离线逐时刻判定。可撤销保证回溯后状态正确。

#

38. 线段树套 Splay 在区间翻转与区间插入的工程实现。

请说明线段树套 Splay 在区间翻转与区间插入中的工程实现?

  • 区间操作
  • Splay 区间维护
  • 树套树

区间翻转与区间插入(如维护序列并支持区间翻转、插入、删除)通常用 Splay(平衡树)直接实现:用 Splay 把区间 [l,r] 提取到一棵子树,打翻转懒标记或插入/删除。线段树套 Splay 用于"区间 + 值域"的复合操作(如区间内 K-th、区间内前驱后继):外层线段树按位置,内层 Splay 维护位置区间内的值域。区间翻转/插入主要用 Splay 的区间操作(splay 到区间两端),外层线段树则用于区间值域查询。工程上,单序列用 Splay 直接做区间翻转/插入,树套树用于多维操作。

Splay 的区间操作(提取区间、打标、插入删除)是处理区间翻转/插入的主力;线段树套 Splay 增加"值域"维度用于区间内值域统计。选择取决于单维还是多维操作。

#

39. Segment Tree Beats 的适用条件中需要维护"次大值/次小值"与"最大/最小出现次数"的节点信息?

请说明 Segment Tree Beats 的适用条件,以及为何需要维护次大值/次小值与最大/最小出现次数?

  • 适用操作
  • 节点信息设计
  • 三元组必要性

Segment Tree Beats 适用于"区间取最值(chmin/chmax)+ 区间加 + 区间求和/最值"的复合操作,其适用条件是操作能通过"最大/次大值区分度"实现 O(1) 分支。节点需维护 max、second max、max 出现次数(chmin 用)以及 min、second min、min 出现次数(chmax 用)。原因:chmin(x) 时,若 x ≥ max 直接返回;若 second max < x < max,则只有最大值被改为 x,此时只需更新 max 与 count 并打懒标记(O(1));仅当 x ≤ second max 才需递归。次大值与计数使"是否只影响最大值"可判定,从而获得势能保证。没有次大值/计数,无法区分"整段都变"与"只变最大值",也就无法 O(1) 分支。

次大值与出现次数是"区分 l 是否只影响最大值"的关键,是 O(1) 分支与势能分析的前提。若只维护最大值,chmin 无法判断能否 O(1) 处理,复杂度退化。

#

40. 区间取模(区间 mod x)为什么能被势能分析约束,每个数取模后至多减半,总操作次数 O((n+q) log A) 的直觉?

请说明区间取模(区间 mod x)为何能被势能分析约束,即每个数取模后至多减半、总操作次数 O((n+q) log A) 的直觉?

  • 取模的减半性质
  • 势能分析
  • 复杂度直觉

区间取模操作:对区间内每个数 a,若 a ≥ x 则改为 a mod x。关键观察:若 a ≥ x,则 a mod x < x 且 a mod x ≤ a/2(因为 a mod x < x ≤ a/2 当 x ≤ a/2,或 a mod x = a-x < a/2 当 x > a/2)。因此每个数被"真正取模"一次后至少减半,最多被取模 O(log A) 次(A 为初始最大值)就变为 0/1(不再变化)。势能定义为"所有数之和的 log"或"值得改变次数",取模使其单调下降,每次取模 O(1) 更新,总取模次数 O(n log A),故总操作 O((n+q) log A)。线段树维护区间最大值,若最大值 < x 则整段跳过(O(1)),否则递归。

势能直觉是"取模使数至少减半",故每个数更新次数 O(log A)。线段树用区间最大值判断整段是否可跳过,只有最大值 ≥ x 才递归,总代价 O((n+q) log A)。

#

41. Segment Tree Beats 在 lazy 势能分析的双势能标记工程实现。

请说明 Segment Tree Beats 在 lazy 势能分析中的双势能标记工程实现?

  • 双势能
  • 懒标记
  • 标记传播

Segment Tree Beats 处理 chmin 与 chmax 复合操作时,需维护两套 lazy 标记(对 max 的标记与对 min 的标记),即"双势能标记"。chmin 的懒标记只影响最大值,chmax 的懒标记只影响最小值,二者同时存在时需按优先级传播(先处理更受限的)。势能分析中,max 侧与 min 侧的势能分别独立下降,标记传播时需保证两套势能都单调。工程实现要点:区分"只改 max"与"只改 min"的懒标记,传播时先推动 max 侧再 push min 侧,避免冲突;配合次大/次小值判断标记是否可 O(1) 应用。

双势能标记把 chmin 与 chmax 的两套懒标记分离,各自维护势能下降。传播顺序与优先级是保证正确的关键,复合操作因此需要精细的标记管理。

#

42. Segment Tree Beats 在势能线段树与吉司机线段树统一框架。

请说明 Segment Tree Beats 在势能线段树与吉司机线段树(Jsei 线段树)统一框架中的关系?

  • 势能线段树
  • 吉司机线段树
  • 统一框架

吉司机线段树(Jsei tree)是 Segment Tree Beats 的经典实现/推广,二者本质是同一框架:维护 max/second max/count 与 min/second min/count,用势能分析保证区间取最值 + 加 + 求和的均摊复杂度。Segmet Tree Beats 是这类"势能线段树"的统称,吉司机线段树是因 CF 题(吉司机)为前缀的经典实现。统一框架:节点维护"最大/次大/计数 + 最小/次小/计数 + 和 + 懒标记",chmin/chmax 通过次大值区分 O(1) 分支,势能单调下降。该框架统一了区间取最值与复合操作的解法。

"势能线段树"是抽象框架,"吉司机线段树"是其经典实现,两者共享"次大值分支 + 势能分析"的核心。统一框架便于理解与迁移实现。

#

43. Segment Tree Beats 在维护区间最大、次大与计数的三元组标记。

请说明 Segment Tree Beats 中维护区间最大、次大与计数的三元组标记?

  • 三元组定义
  • 合并规则
  • chmin 应用

Segment Tree Beats 的节点维护 (max, secondMax, cntMax) 三元组:max 为区间最大值,secondMax 为严格次大值(不存在则 -∞),cntMax 为最大值出现次数。合并时取两子树 max 较大的为 max,次大值为两子树的 max 与 secondMax 中最大且小于 max 的值,cntMax 为取得 max 的子树的 cntMax 的和。chmin(x) 应用:若 x ≥ max 不变;若 secondMax < x < max,则把 max 改为 x 并更新和(cntMax 个值变为 x),打懒标记;否则递归。三元组支持"整段只改最大值"的 O(1) 分支。

三元组 (max, secondMax, cntMax) 是 chmin 的"信息基元":它让"哪些值等于 max、改为 x 后和如何变"可 O(1) 计算,从而支持 O(1) 分支与势能分析。

#

44. 区间历史最值与历史和的 Segment Tree Beats 拓展工程实现。

请说明区间历史最值与历史和的 Segment Tree Beats 拓展工程实现?

  • 历史最值
  • 历史标记
  • 拓展实现

区间历史最值(历史最大值/最小值)与历史和(历史版本的和)需要额外的"历史懒标记":记录区间内各元素在历史中达到的最值及其时间。工程实现:在普通懒标记基础上,增加"历史最值懒标记"(记录当前懒标记在历史中达到的最值),每次 push 时用历史标记更新子节点的历史最值。维护历史最值需节点同时记录"当前最值"与"历史最值",懒标记也需"当前"+ "历史"两套。取最值/加操作后,用历史标记记录历史峰值。复杂度仍由势能保证,实现复杂。

历史最值/历史和的难点是"懒标记的历史传播":懒标记需记录其历史峰值,push 时更新子节点历史信息。这使标记系统从"当前"扩展到"当前+历史"。

#

45. Segment Tree Beats 与普通懒标记线段树的边界中哪些操作仍需 O(log n) 单次而非势能均摊?

请说明 Segment Tree Beats 与普通懒标记线段树的边界:哪些操作仍需 O(log n) 单次而非势能均摊?

  • 普通懒标记操作
  • 势能均摊边界
  • 操作分类

普通懒标记线段树支持的操作(区间加、区间赋值、区间求和/最值)每次 O(log n) 最坏可保证,因为它们可用"区间整体懒标记"直接传播,无需势能。而 Segment Tree Beats 的取最值(chmin/chmax)操作是"势能均摊"的:单次可超过 O(log n)(需递归),但长期均摊 O(log² n)。边界:区间加、赋值、求和、最值等"普通操作"仍是 O(log n) 单次;取最值(chmin/chmax)是势能均摊。判断某操作是否 O(log n) 单次:取决于能否用"区间整体性质"(懒标记)决定而不递归。若操作只影响少数值(如取最值),需递归,故势能均摊。

边界在于"懒标记能否覆盖整段"。普通操作(加/赋/求和)可用整段懒标记 O(log n);取最值只在"次大/最大之间"才 O(1) 分支,否则递归,故均摊。据此区分"最坏 O(log n)"与"势能均摊"。

#

46. 扫描线求矩形面积并中为什么用 y 轴离散化加线段树维护覆盖次数,覆盖计数与区间求和的区别?

请说明扫描线求矩形面积并为何用 y 轴离散化加线段树维护覆盖次数,以及覆盖计数与区间求和的区别?

  • y 离散化
  • 覆盖次数线段树
  • 覆盖计数 vs 区间和

扫描线求矩形面积并:按 x 排序事件,用线段树维护 y 轴上的覆盖层数。y 轴离散化把连续坐标压缩为 O(n) 个关键区间,线段树节点对应坐标区间,维护"覆盖层数"(该区间被多少矩形覆盖)与"覆盖长度"(层数 > 0 的区间总长度)。覆盖计数与区间求和的关键区别:区间求和是"累加值"(可逆、可减),覆盖计数是"层数"(差分 +1/-1),覆盖长度非"层数之和"而是"层数>0 的长度"。因此线段树维护的是"最小覆盖层数 + 覆盖长度",而非"区间和"。当层数>0 时覆盖长度为区间全长,否则由子节点长度和为。这使面积并退化为"非零覆盖"判定。

y 离散化把连续区间压缩为线段树区间,覆盖层数用差分维护(+1/-1),覆盖长度 = 层数>0 的长度。与区间求和的差异在于覆盖长度是"非零判定"而非"值累加",需特殊维护。