单调队列学习笔记
单调队列
P1886 滑动窗口 /【模板】单调队列
「单调」指的是元素的「规律」——递增(或递减)。
「队列」指的是元素只能从队头和队尾进行操作。
要求的是每连续的
也就是说——当满足以上条件时,可将前面的数 "弹出",再将该数真正
这就相当于维护了一个递减的队列,符合单调队列的定义,减少了重复的比较次数,不仅如此,由于维护出的队伍是查询范围内的且是递减的,队头必定是该查询区域内的最大值,因此输出时只需输出队头即可。
显而易见的是,在这样的算法中,每个数只要进队与出队各一次,因此时间复杂度被降到了
#include <iostream>
#include <cstdio>
#include <deque>
using namespace std;
const int maxn = 1e6 + 5;
int n, m;
int a[maxn];
deque<int> q;
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
{
while (!q.empty() && a[q.back()] > a[i])
q.pop_back();
q.push_back(i);
if (i >= m)
{
while (!q.empty() && q.front() <= i - m)
q.pop_front();
printf("%d ", a[q.front()]);
}
}
printf("\n");
while (!q.empty())
q.pop_back();
for (int i = 1; i <= n; i++)
{
while (!q.empty() && a[q.back()] < a[i])
q.pop_back();
q.push_back(i);
if(i>=m)
{
while(!q.empty()&&q.front()<=i-m) q.pop_front();
printf("%d ",a[q.front()]);
}
}
return 0;
}
单调队列应用场景:
单调队列(Monotonic Queue)是一种数据结构,常用于解决一些与滑动窗口相关的问题。它可以在
- 在队尾添加元素
- 在队头移除元素
- 获取当前队列中的最大(或最小)元素
使用单调队列的典型场景包括:
-
滑动窗口最大值(或最小值)问题:给定一个数组和窗口的大小,需要找到每个窗口内的最大(或最小)值。单调队列可以帮助我们在窗口滑动的过程中高效地获取最大(或最小)值。
-
求解滑动窗口的某种性质:有时候我们需要在滑动窗口中求解的不仅仅是最大(或最小)值,还可能是其他一些特定的性质,比如窗口内的元素之和、平均值等。通过维护一个适当的单调队列,我们可以在滑动窗口中高效地求解这些性质。
-
解决一些需要在固定大小的窗口中维护最大(或最小)值的问题:比如在一个数据流中,需要不断更新当前窗口的最大(或最小)值。单调队列可以帮助我们在数据流中高效地维护这些值。
P1440 求m区间内的最小值
单调队列板子题,使用单调队列时需注意边界处理情况。手玩一遍即可。
P1714 切蛋糕
P10893 城市化发展委员会
P10878 [JRKSJ R9] 在相思树下 III
本文作者:vanueber
本文链接:https://www.cnblogs.com/vanueber/p/18668576
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步