线性优化技巧学习笔记
单调栈
现有一数列
a ,请在\Theta(n) 的复杂度,对每个i 求出最小的j > i 使得a_j > a_i ,记为f_i .若不存在这样的j ,记f_i = n + 1 .
这个问题称作 NGE 问题(Next Greater Element).用到单调栈的时候,99% 都是这个背景.应用如下:
- 若
i 的 NGE 是j ,则j 的 LLE(Last Less) 是i .在代码中的体现是,若j 将i 弹出栈,则i 的 NGE 是j ,j 的 LLE 是i .这条性质看上去很平凡,写在这里是提醒读者:单调栈中的 NGE 关系并不是单向的弹出关系,被弹的元素和弹了它的元素,是一种双向的关系. - 若
i 的 NGE 是j ,则a[i + 1 \ldots j - 1] \le a_i < a_j .否则,j 不符合 NGE 中的 N.P1823.P2866.这提示我们:考虑一个元素接下来连续的比自己小的一段 的问题,实质就是在找一个元素的 NGE,考虑单调栈. - SP1805 HISTOGRA 条形图中的最大矩形.也是很经典的单调栈.考虑以一个矩形为顶,向左向右最多延伸多少,发现本质是 LLE 和 NLE 问题.
- P1950.考虑统计下边界在第
i 行的矩形数,则问题变成 HISTOGRA 从问最大矩形变成矩形数.这个比上面的难点在于不可重复,上面的做法很明显重复了.但是思考一下上面重复的可能性:唯一一种重复的可能是存在a_i = a_j ,并且考虑a_i 或a_j 时,向左向右延伸会考虑到对方. - 还是说明一下为什么这是唯一一种重复的可能.首先如果延伸的过程存在
a_i = a_j ,那这个矩形实际上以从i 延伸和从j 延伸都会被统计到.而如果a_i < a_j ,则从a_i 延伸出来的矩形并不会贴到j 的顶,当然不属于从j 贴顶再延伸的矩形. - 如何解决?考虑钦定
a_i = a_j 时,如果先前会互相延伸到对方,那么现在我们只允许i 延伸到j ,而不允许j 延伸到i .这也就意味着从j 向左延伸时,我们不再允许跨过a_k = a_j ,即 LLE 中 L 的严格小于应该为 LNGE,NG 代表不大于(\le ).这样以来,即可保证统计的不重不漏. - ABC420F & P13647.相比于 P1950 再上难度.考虑我们每次统计的矩形,以
(i, j) 为底,高度1 \sim u_i(j) 任选.现在考虑宽度为1 的矩形,宽度为2 的矩形,宽度为3 的矩形……各有多少个,这可以转化为下面这个问题: - 线段
[l, r] 上p \in [l, r] ,考虑[l, r] 中包含了p 的子线段,统计每种长度的数量. - 假设
l = 1, r = 6, p = 3 . - 长度为
1 的线段:[3, 3] . - 长度为
2 的线段:[2, 3], [3, 4] . - 长度为
3 的线段:[1, 3], [2, 4], [3, 5] . - 长度为
4 的线段:[1, 4], [2, 5], [3, 6] . - 长度为
5 的线段:[1, 5], [2, 6] . - 长度为
6 的线段:[1, 6] .
观察不难发现,长度为
回顾一下这个矩形问题,其实暗含的是这样一个想法:对于一个数组
这样以来,每个区间都有唯一的代表.而上面 NLE 和 LNGE 的配合,其实就是在找对于一个