单调栈与单调队列
单调栈
数组/栈中的数满足单调性质(递增或递减),可查询 \(1 - i\) 中的最小值或是最大值。
实现:(以单调上升举例)
将数按顺序压入栈中,若新压入的数小于前一个数(不满足单调性),则弹出前一个数,继续向前比较,直至满足大于前一个数(满足单调性)时将此数入队。
代码:
while(s[now] < a[i]){ //不满足条件
now --; //弹出
} s[++ now] = a[i]; //入栈
应用:
常用于寻找一个数右侧第一个大于或是小于它的数。或是用于优化 dp 的效率。
习题:
Patrik 音乐会的等待
单调队列
类似于单调栈,但可控制区间长度,不一定是单调栈的 \(1 - i\) ,可以是 \(j - i\) 。
实现:
在单调栈的基础上添加控制左端点的变量。
代码:
l = 1; r = 0; //初始化左右端点位置
while(l <= r && a[i] > a[s[r]]){
r --; //弹出
}
s[++ r] = i; //入队
while(l <= r && s[l] + k <= i){ //若长度不满足限制
l ++; //左端点右移
}
应用:
常用于查询一段区间中的最大值或是最小值。
单调栈与单调队列
单调队列灵活性比单调栈更高,可控制查询区间。但在没必要控制时直接使用单调栈即可。