丹钓战
其实就是简记一下单调栈的一个很好的理解方式,来源 writings.sh。
以单调递减的单调栈为例。因为如果要加入元素肯定都要先依次弹出栈顶,使加入新元素后能满足单调性。这里就是弹出不比新元素大的栈顶。假设目前准备加入一个新元素 ,正在弹栈(栈顶是需要被弹出的,),栈底是 。那么,有如下的性质:

- 。按弹出的定义就有了。
- 一定是目前扫到的最大值。否则一定会有元素使它被弹出。
- 在原数组中下一个不比它小的元素为 。因为如果中间存在一个不比它小的元素,一定会在 之前使它被弹出。这个可以解决 NGE(Next Greater Element)问题。
- 假设 已经弹出了一些栈中元素,那么由 1 有 ,又因为栈是单减的,有 。这就是 “ 的局部长板效应”:。
- 是在栈内上一个元素 和 之间(不含端点)的最大元素。首先由 3 可以得到一部分,而如果在 到 之间存在比 更大的元素 ,假设 , 就会被弹出,矛盾;而如果 ,它就会存在于栈中 和 之间,但是栈中 和 之间显然没有元素,矛盾。这就是 “ 的局部长板效应”。和悬线法有点关系,也可能用于更新贡献( 到 的位置,见 Pudding Monsters)。
顺便说一下悬线法。感觉更适用于单个元素扩展的感觉(有点像笛卡尔树)。
诶多,悬线法还是挺帅气的 (′д` )…彡…彡,至少随便处理个啥的都很优雅:
for (int i = 1; i <= n; i++) l[i] = r[i] = i;
for (int i = 1; i <= n; i++)
while (l[i] > 1 && a[i] < a[l[i] - 1]) l[i] = l[l[i] - 1];
for (int i = n; i; i--)
while (r[i] < n && a[i] <= a[r[i] + 1]) r[i] = r[r[i] + 1];