算法与数据结构 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\)。、

用途

当使用斜率优化 DP 时,状态转移方程形如:

\[dp[i]=\min/\max\{a[i]\times b[j]+d[j]\}+c[i] \]

上面的式子,去掉 \(\min/\max\) 后简单变形:

\[dp[i]-c[i]=d[j]-(-a[i]\times b[j]) \]

\[b=y-k\times x \]

如果式子中的 \(k\) 部分和 \(x\) 部分均不单调,则可以用李超线段树维护凸壳,以较快的时间复杂度找到最优决策点。

原理

理论

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

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

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

实现

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

posted @ 2025-07-25 20:58  cwkapn  阅读(28)  评论(0)    收藏  举报