李超树
(不得不抱怨一下我现在正在用的这个键盘,好难打,如果有啥子笔误请指出)
基础
支持在线插入一条线段,一条直线,插入线段的极限时间复杂度是\(O(log^2)\),插入一条直线的时间复杂度是\(O(log)\) 的。
支持查询一个已知 \(x\) 的竖线与插入的直线段的交点的最值。
实现
与普通线段树不同,我们的信息现在分散地保存在每一个节点上,而不是仅仅集中于叶节点。
类似标记永久化,每一条根到叶子的路径都保存了潜在的具有优势的线段(直线)。
当更新时,我们将原线段与新线段进行比较,将在区间中点(整数中点)处较高的保留,称其为优势线段,另外一条线段被称为劣势线段。
然后我们将劣势线段下放到其相对于优势线段更有优势的区间——即劣势线段的优势区间。
这样不仅保证了复杂度(一条线段覆盖的区间最多被分作\(log_2{len}\)份,而每份又只会被下放\(log_2{n}\)层,所以关于线段下放的时间复杂度是双\(log\)的),还保证了正确性(显然,你将劣势线段下放到期可能成为优势线段的优势区间这个行为就保证了下放不会遗漏)。
总而言之,实现起来还是很好写的,唯一要注意的就是精度的问题。
运用
如果仅仅是插入直线,那李超线段树的运用也太狭隘了。
我们发现,有的问题中,我们可以把我们的式子(\(DP\)式或者别的什么)写作一个很类似直线表达式的东西,这个东西就可以用李超线段树维护。
举个例子:\(F_i=\min_{j=1}^{i-1}{a*F_j*i+b*j*S_i}\)(里面的变量名乱取的,反正你记住跟\(i\)有关的是常量就对了)。我们可以发现,如果我们将\(j\)看作自变量的话,\(Fi\)就是因变量,而什么\(a\)啊\(F_j\)啊之类的就是常量了。你看,是不是就成了一个直线表达式啊。
那么我们就可以用李超线段树维护了。
小Trick
像上面那种情况,有两个自变量,这该怎么办呢?
如果我们发现他没有常数(就是比如\(a*x+b\)中的那个\(b\)),那么我们不妨无中生\(b\),让他整体除以一个\(i\),变成这样:
\[$F_i=\min_{j=1}^{i-1}({a*F_j*\frac{i}{i}+b*j*\frac{S_i}{i}})*i \]于是我们就可以把\(\dfrac{S_i}{i}\)看作自变量,然后套模板了。
标签:直线,log,线段,我们,插入,复杂度,李超树 From: https://www.cnblogs.com/Ariginal/p/18012844