算法与数据结构 7.5 - 李超线段树

目录

  • 前言
  • 由来
  • 作用
  • 原理
    • 理论
    • 实现

前言

其实李超线段树应该属于斜率优化的一部分,因为这种数据结构常见用法似乎就是斜率优化。但因为不常见(一般是出题人懒得写),所以分到单独的一章。

由来

李超线段树是杭州学军中学的李超(IOI 2012 Au)发明的。

作用

要求在平面直角坐标系下维护两个操作,强制在线:

  1. 在平面上加入一条线段。记第 \(i\) 条被插入的线段的标号为 \(i\),两端点 \((x_0,y_0)\)\((x_1,y_1)\)
  2. 给定一个数 \(k\),询问与直线 \(x = k\) 相交的线段中,交点纵坐标最大的线段的编号。

\(1 \leq n \leq 10^5\)\(1 \leq k, x_0, x_1 \leq 39989\)\(1 \leq y_0, y_1 \leq 10^9\)

原理

理论

暴力的想法是维护 \(x=i\ (1\le i \le 39989)\) 上最高点的位置,但这样做修改是 \(\mathcal{O}(n\times \text{len})\ (\text{len}=39989)\) 的,显然无法通过本题。考虑到这道题需要进行大量的区间修改操作,于是想到线段树维护答案。

考虑让线段树上每个节点维护 \(x=\frac{l+r}{2}\) 处的最高点的 \(y\) 和线段编号。对于懒惰标记(lazy tag)的下传,分类讨论原区间中的最优线段和新加线段的位置关系:

  • 新线段在老线段的上方时:直接更新即可。
  • 新线段在老线段的下方时:丢弃。
  • 新线段和老线段交叉时,不妨设交点在左子区间:
    • 对于右子区间,考虑上面两种处理方法;
    • 对于左子区间,考虑递归处理。
      其余部分按常规线段树处理即可。时间复杂度和普通线段树一样。

实现

原来的代码过于臃肿,正在重写。