单调队列学习笔记
前言
我们常说:“我又被单调队列了/kk”,意为“我比比自己小还比自己强的人吊打了”。
今天我们赖了解什么是“单调队列”。
分析
毫无疑问,最开始必定想到的是 的暴力。
代码不贴啦,必定 。
考虑优化。
要求的是每连续的 个数中的最大值,很明显,当一个数进入所要 "寻找" 最大值的范围中时,若这个数比其前面(先进队)的数要大,显然,前面的数会比这个数先出队且不再可能是最大值。
- 摘自 OI Wiki。
这是复杂度为 。
对于样例分析
1 3 -1 -3 5 3 6 7
操作 | 队列 |
---|---|
1 入队 |
{1} |
3 入队 |
{1,3} |
-1 入队,队内元素大于 -1 的出队 |
{-1} |
-3 入队,队内元素大于 -3 的出队 |
{-3} |
5 入队 |
{-3,5} |
3 入队,队内元素大于 3 的出队 |
{-3,3} |
6 入队,-3 不在窗内,出队。 |
{3,6} |
7 入队 |
{3,6,7} |
Code
- 摘自 OI Wiki。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define maxn 1000100
using namespace std;
int q[maxn], a[maxn];
int n, k;
void getmin() { //得到这个队列里的最小值,直接找到最后的就行了
int head = 0, tail = 0;
for (int i = 1; i < k; i++) {
while (head <= tail && a[q[tail]] >= a[i]) tail--;
q[++tail] = i;
}
for (int i = k; i <= n; i++) {
while (head <= tail && a[q[tail]] >= a[i]) tail--;
q[++tail] = i;
while (q[head] <= i - k) head++;
printf("%d ", a[q[head]]);
}
}
void getmax() { //和上面同理
int head = 0, tail = 0;
for (int i = 1; i < k; i++) {
while (head <= tail && a[q[tail]] <= a[i]) tail--;
q[++tail] = i;
}
for (int i = k; i <= n; i++) {
while (head <= tail && a[q[tail]] <= a[i]) tail--;
q[++tail] = i;
while (q[head] <= i - k) head++;
printf("%d ", a[q[head]]);
}
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
getmin();
printf("\n");
getmax();
printf("\n");
return 0;
}
//deque实现
#include <cstdio>
#include <queue> // 提供deque
#define MAXN 2000005
using namespace std;
struct Num{
int index,x;//需要记录单调队列内每个数的入队时间(index)和大小(x)
};
int a[MAXN]; //原数组
deque<Num> q; //单调队列
int main(void){
int n,m; //n表示序列长度,m表示滑动窗口长度
Num t;//保存当前元素
//输入
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
//问题解决
for (int i=1;i<=n;i++){
//先输出数a[i]前的最小值
if (q.empty()) //q空,即a[i]前没有元素
printf("0\n");
else { //否则判断队头是否需要出队并输出范围内的队头
if (q.front().index+m<i) //队头已经超出滑动窗口范围
q.pop_front(); // 弹出队头
printf("%d\n",q.front().x); //此时队一定非空(想想为什么)
}
while ((!q.empty()) && q.back().x>=a[i])
//当队列非空时,不断弹出队尾比当前元素大的元素
q.pop_back();
t.index=i;
t.x=a[i];
q.push_back(t);//将当前元素入队
//注意:当前元素无论如何都会入队(想想为什么)
}
return 0;
}
无耻求赞求关注(((q(≧▽≦q)
本文作者:int32
本文链接:https://www.cnblogs.com/lycqwq/articles/mono-queue-note.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 Redis 客户端超时到 .NET 线程池挑战
· C23和C++26的#embed嵌入资源指南
· 「EF Core」框架是如何识别实体类的属性和主键的
· 独立开发,这条路可行吗?
· 我在厂里搞 wine 的日子
· 他没买 iPad,而是花了半年时间,为所有“穷学生”写了个笔记神器
· Visual Studio 现已支持新的、更简洁的解决方案文件(slnx)格式
· 只需一行命令,Win11秒变Linux开发主机!
· 从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析
· 2025年中总结:我想我克服公众演讲的恐惧了,一个社恐分子突破自我的故事