斜率优化 & 李超线段树 乱记

问题:给出 \(n\) 个二元组 \((x_i, y_i)\)\(q\) 次给定 \(k\),询问 \(\max\limits (kx_i + y_i)\)\(k\) 的范围为 \(V\)


数形结合的斜率优化。

把给定的 \(k\) 记做 \(k'\)

发现这个 \(a_ix + b_i\) 的形式像一个直线表达式。
对比一下正常的直线的表达式 \(y = kx + b\iff b = -kx + y\)

于是令 \(k = -k', x = x_i, y = y_i\),那么现在就相当于是 \(b = -(-k')x_i + y_i\),求 \(b\) 的最大值。

考虑一下 \(b\)\(-k'\) 的实际含义,实际上是这条直线的截矩和斜率(截矩:代入 \(x = 0\)\(y\) 的值)。
于是这个 \(b\) 就可以理解成,过 \((x_i, y_i)\) 的斜率为 \(-k'\) 的直线的截矩。

因为是要求最大截矩,那么就可以当作是先让 \(b\) 变得无穷大,然后让这条斜率为 \(-k'\) 截矩为 \(b\) 的直线不断减小截矩,也就是往下平移,直到经过了一个 \((x_i, y_i)\),那么此时就求得了最大的 \(b\)

那么根据这个思想,就只需要关心整个 \((x_i, y_i)\) 点集的上凸壳了。
这是因为不在凸壳上的肯定是形如被凸壳包住了,如果直线经过了这个点那么往上平移去经过上凸壳上的点肯定更优。

那么此时这条斜率为 \(-k'\) 的直线当取到 \(b\) 最大值是就应该是这个上凸壳的切线。

对于上凸壳的维护和切线切到哪是容易的,因为可以快速知道上凸壳上相邻两点间的斜率 \(\frac{y_j - y_i}{x_j - x_i}\)
对于插入一个点就可以先插入,再更新前后的上凸壳:对于上凸壳上按顺序相邻三个点 \(a, b, c\),当 \(k_{ab}\ge k_{ac}\ge k_{bc}\) 时这个凸壳合法。
对于找切线切到哪,对于上凸壳上按顺序相邻三个点 \(a, b, c\),当 \(k_{ab}\ge -k'\ge k_{bc}\) 时可以认为切到了 \(b\) 这个点。

对于插入可以用平衡树维护,对于找切点可以通过二分相邻两点的斜率与 \(-k'\) 的大小关系找到,于是可以做到时间复杂度均摊 \(\mathcal{O}((n + q) \log n)\),空间复杂度 \(\mathcal{O}(n)\)

特殊的,在满足一些条件的时候,一些部分的复杂度是线性的:

  • \(x_i\) 单增:那么插入的点一定在最后,每次更新这个上凸壳也只会从后往前,可以用一个栈维护,插入复杂度为均摊 \(\mathcal{O}(n)\)
  • \(x_i\) 单增且 \(-k'\) 单降:查询的斜率越来越小,那么切点就一定越来越靠后(越靠后斜率越小),所以可以直接用一个双端队列维护,头就代表目前的切点,尾就负责插入操作,那么插入询问都是均摊线性的,总复杂度均摊 \(\mathcal{O}(n + q)\)

需要注意的是斜率优化的复杂度都涉及均摊,所以不能可持久化。


很暴力的李超线段树。

核心思想:对于两条直线 \(l_1: y_1 = k_1x + b_1, l_2 : y_2 = k_2x + b_2\),在 \(x\) 这个轴从左往右扫的情况下,两条直线的大小关系至多只会转换一次。
也就是可能 \(x\) 在一个前缀的时候都有 \(y_1 > y_2\),但在过了两直线交点后,后缀的 \(x\) 都有 \(y_2 > y_1\) 了。

所以说可以用线段树,每个线段树的节点区间 \([l, r]\) 维护一个对于当前区间的优势直线 \(l_{[l, r]}\)
但是这里的优势指的不是对于整个 \([l, r]\),而是对于 \(mid = \lfloor\frac{l + r}{2}\rfloor\) 而言。

那如果说一条直线 \(l\) 在这个线段树区间的 \(mid\) 的取值没有 \(l_{[l, r]}\) 优,但是在一些其他的位置比 \(l_{[l, r]}\) 优怎么办?
那么这个时候考虑前面说的,大小关系只会至多转换一次。
这说明 \(l\)\(l_{[l, r]}\) 优的区间应当是 \((-\infty, x](x < mid)\)\([x, +\infty)(x > mid)\)
这个时候结合上线段树 \([l, r]\) 的儿子是 \([l, mid], (mid, r]\),那么这说明 \(l\)\(l_{[l, r]}\) 优的这个区间只会在 \([l, r]\) 的一个儿子中,那么此时就往这个优一些的儿子继续递归下去就可以了。
实现的时候可以直接考虑代入 \(l, r\) 的两个端点值看是否更优然后递归。

对于询问 \(k\),那么就考虑直接把 \(k\) 到根节点这 \(\log V\) 个节点的优势直线拉出来,取一个最大值就可以了。
为什么是对的?因为考虑不在这 \(\log V\) 个节点的优势直线肯定是在插入递归的时候就保证了在包含 \(k\) 的这个区间不会比这个区间的优势直线更优。

时间复杂度为 \(\mathcal{O}((n + q)\log V)\),空间复杂度为 \(\mathcal{O}(\min\{n, V\})\)

值得一提的是对于李超线段树的区间 \([l, r]\) 的儿子其实设成 \([l, mid), (mid, r]\) 会合理些,而且这能让节点上界的 \(2V - 1\) 变成 \(V\),空间常数 \(/2\),询问常数也能小一些?(可以在 \(mid = k\) 时就退出,不需要问到叶子)。

李超线段树的一大优势是好写且常数小,在不保证任何信息的情况下应当比斜率优化的平衡树优秀很多。

但是有个问题是李超线段树的复杂度是 \(\log V\),有没有好一点的做法呢?
如果支持离线的情况下,可以考虑把所有询问的 \(k\) 离线下来排序,然后对于线段树的区间 \([l, r]\) 实际维护 \([k_l, k_r]\) 的值,中间代入的值也由 \(mid\) 变为 \(k_{mid}\)
于是就可以把 \(V\) 优化成 \(q\) 了。

李超线段树是严格的 \(\log V\),所以可持久化李超线段树是有保证的。

李超线段树也有比较厉害的合并做法:
考虑一个暴力的做法是暴力启发式合并加入直线。
但是这实际上并不优,因为例如对于李超线段树 \(T_1\) 的直线 \(l_{[l, r]}\),它在除 \([l, r]\) 子树的结点上一定没有该节点的优势直线优,那么在 \(T_1, T_2\) 合并出的树上,\(l_{[l, r]}\) 也不可能出现在 \([l, r]\) 的子树外。
于是可以考虑对于 \(l_{[l, r]}\),直接在 \(T_2\) 对应的节点 \([l, r]\) 开始插入。
这个的复杂度是均摊 \(\mathcal{O}(n\log V)\) 的,因为每条直线至多向下递归 \(\log V\) 次。


一些更抽象的:
其实这个直线的形式应当是四边形不等式的特化。
实际上斜率优化和李超线段树都可以扩展至普通的贡献满足四边形不等式的做法。

因为四边形不等式就保证了对于任意 \(i < j\),存在一个 \(k_0\) 满足 \(\forall k\le k_0, f_i + \operatorname{cost}(i, k)\le f_j + \operatorname{cost}(j, k), \forall k > k_0, f_i + \operatorname{cost}(i, k) > f_j + \operatorname{cost}(j, k)\)
证明待补。

这也就说明了两个决策的优劣只会转换一次。
于是依然可以把 \(f_i + \operatorname{cost}(i, k)\) 看作一条直线,那么就可以直接上李超线段树了。
复杂度为 \(\mathcal{O}(c(n)n\log n)\),其中 \(c(n)\) 为计算 \(f_i + \operatorname{cost}(i, k)\) 的复杂度(特化:为直线时 \(c(n)\) 为常数)。
这个想法似乎也被称作“广义李超线段树”。

套用到斜率优化的做法上,那么就考虑用双端队列维护上凸壳的做法。
对于直线的形式,相当于是询问斜率,对于上凸壳也要维护相邻两点斜率并要求斜率递减。
类似的,考虑把询问的位置 \(k\) 当作斜率,维护一个上凸壳。
需要考虑的信息就是凸壳上相邻两点点在决策优劣交换的位置,也就是上文的 \(k_0\)(也就相当于相邻两点的斜率)。
但是因为一个普通的 \(f_i + \operatorname{cost}(i, k)\) 并不具有很好的性质,对于 \(k_0\) 的求解大多需要二分,时间复杂度为 \(\mathcal{O}(c(n)n\log n)\)(特化:为直线时可以直接通过两点 \(\mathcal{O}(1)\) 求出 \(k_0\))。
其实这个做法也就是解决贡献满足四边形不等式问题的较为常见的做法“二分队列”(好像叫这个名字?)。

相比较起来,在贡献并不特殊的情况下,还是用李超线段树吧,常数小一些并且显著好写。

例题:
QOJ 8725 Train


小故事:
唯一放的一道例题其实是 APIO2024 T2。
我就在场上写了“二分队列”做法,写的非常长且抽象(可能是我的问题)。
也就是在赛后 11d10xy 大神告诉我可以直接李超线段树维护启发了我,也就有了这个第三部分。
(所以在现在才写出来吗。)

posted @ 2025-02-18 12:11  rizynvu  阅读(119)  评论(0)    收藏  举报