算法学习笔记(31): 李超线段树

李超线段树是一种按照值域维护一次函数最值的数据结构,其核心在于一次函数和值域的双单调性。

如果预先对于值域离散也可以维护其最值。

也就是说只要满足时一次函数,以及下标的单调性都可以利用李超线段树维护。

李超线段树就是利用线段树来维护一次函数的最值,每一个结点对应了一个区间 [l,r]

我们定义一个区间 [l,r] 的最优函数 kx+b 为在 l+r2 处为最值的函数。

最优函数满足在中点是最值,但是不一定满足在端点是最值,所以需要分为左右两个区间判断。

然而对于一次函数来说,如果满足时最优函数,那么对于另一条函数,只能有左半或者右半是优于它的:

于是更新有三种情况:

  • 如果当前函数优于原函数,那么交换,进行下面的判断
  • 如果当前函数在左端点优于原函数,那么递归更新左区间
  • 如果当前函数在右端点优于原函数,那么递归更新右区间

注意到如果满足的最优函数,那么不存在一条两边都大于它的函数,此时至多进入一个区间,根据线段树有 O(logn) 层,所以更新的复杂度是 O(logn) 的。

单点查询的时候需要注意,需要利用经过的每一个节点的最优函数来更新答案,这样一定是不劣的。

那么如果这个一次函数限定了值域,那么意味着这个函数只能更新部分的区间。

那么考虑到线段树本身可以将一个区间拆分为 O(logn) 个区间,然后我们对于这些区间用此函数来更新即可。可以做到 O(log2n) 维护区间函数最值。


板子题 李超线段树 我就不细说了。

这里说说如何利用李超线段树优化 DP。

能用斜率优化的 DP 都可以使用李超树维护,并且一般都可以过( 107 也不是不可以,只是需要大力卡常而已)

式子形如:fi=maxfj+ci×cj

此时我们将 cj 看作 k, fj 看作 b,那么问题转化为有一堆 y=kx+b,现在给定 x=ci,求最值。

如果 ci 的值域很小,可以支持 O(VlogV) 的时间和 O(V) 的空间,那么十分简单,直接利用李超线段树维护即可。

但是如果 ci 不连续,但是观察到一共有 O(n)ci,于是考虑离散化,排序后将它们映射到 [1,n] 的整数上,考虑下标是单调的,那么李超线段树所依赖的最优函数的性质任然成立,所以可以 O(nlogn) 的维护这颗李超线段树了。

但是接下来如果我们限制了转移的区间:fi=maxikj<ifj+ci×cj

首先,如果 ci 是单调的,那么是简单的,这意味着离散化后 ici 意味着下标和值域是匹配的,所以可以利用区间维护最优函数来做,这样复杂度是 O(nlog2n) 的。

如果 ci 是不单调的,那么这题就太阴间了 QwQ,但是任然可以利用李超线段树解决。

利用线段树分治,维护支持撤销的一棵李超线段树,然后在 DP 的过程中边求答案边更新分治线段树即可,这样复杂度也是 O(nlog2n) 的。

posted @   jeefy  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示