单调栈与单调队列优化 dp
单调栈
将一个元素插入单调栈时,为了维护栈的单调性,需要在保证将该元素插入到栈顶后整个栈满足单调性的前提下弹出最少的元素。
例如,栈中自顶向下的元素为 。
插入元素 时为了保证单调性需要依次弹出元素 ,操作后栈变为 。
模板题:P5788 单调栈
CF547B Mike and Feet
求出所有长度为 的子序列 中最大的子序列值。子序列值定义为这个子序列当中的最小值。
思路:
正难则反。我们枚举所有的子序列值(最小值),然后向左右两边扩展能到的最大长度区间。
举个例子,序列 1,3,2,0,5
,如果我们当前枚举最小值 2
( 号位置),那么这个区间左端点最多扩展到 号位置,右端点最多扩展到 号位置。区间 就是能扩展到的最大长度区间。但是区间 则不合法,因为此区间最小值非 为 。
一般的,若当前枚举最小值位置为 ,左右扩展区间为 ,满足 ,那么长度为 的区间都能取到子序列值 。
由于区间 是前缀,可以不用线段树维护。这里给出两种代码。
单调队列
例题 单调队列:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, k, a[N], q[N];
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
int hd = 1, tl = 0;
for (int i = 1; i <= n; i++) {
while (hd <= tl && q[hd] <= i - k) hd++;
while (hd <= tl && a[q[tl]] >= a[i]) tl--;
q[++tl] = i;
if (i >= k) cout << a[q[hd]] << ' ';
}
puts("");
hd = 1, tl = 0;
for (int i = 1; i <= n; i++) {
while (hd <= tl && q[hd] <= i - k) hd++;
while (hd <= tl && a[q[tl]] <= a[i]) tl--;
q[++tl] = i;
if (i >= k) cout << a[q[hd]] << ' ';
}
puts("");
}
标签:
单调栈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】