【洛谷P1886】滑动窗口(单调队列)
今天还是学数据结构的一天
滑动窗口 /【模板】单调队列
题目描述
有一个长为
例如,对于序列
输入格式
输入一共有两行,第一行有两个正整数
第二行
输出格式
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
样例 #1
样例输入 #1
8 3
1 3 -1 -3 5 3 6 7
样例输出 #1
-1 -3 -3 -3 3 3
3 3 5 5 6 7
提示
【数据范围】
对于
对于
好了 单调队列 嗯 单调队列
单调队列的思路是什么呢?
我的理解是 维护一个单调的队列(废话)
然后 对于准备入队的元素 将之前相比它生存力更低(例如本题求最小值时 比它大又更靠前的元素)出队
同时维护一下队长(chang)
所以 STL中应该用deque 本题用的是手搓
代码如下~
单调队列后面还会用到优化DP中 很重要 要好好学哦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include<bits/stdc++.h> using namespace std; int n,k; int a[2000005]; int p[2000005],q[2000005]; void minimum(){ int tail=0,head=1; for ( int i=1;i<=n;i++){ while (head<=tail&&q[tail]>=a[i]){ //只要有元素且尾元素比待处理值大就出队 tail--; } q[++tail]=a[i]; p[tail]=i; while (p[head]<=i-k){ //如果超过k个就队首出队 head++; } if (i>=k) printf ( "%d " ,q[head]); //注意这里输出的是队首 } return ; } void maximum(){ int tail=0,head=1; for ( int i=1;i<=n;i++){ while (head<=tail&&q[tail]<=a[i]){ tail--; } q[++tail]=a[i]; p[tail]=i; while (p[head]<=i-k){ head++; } if (i>=k) printf ( "%d " ,q[head]); } return ; } int main(){ scanf ( "%d%d" ,&n,&k); for ( int i=1;i<=n;i++){ scanf ( "%d" ,&a[i]); } minimum(); cout<<endl; memset (q,0, sizeof (q)); memset (p,0, sizeof (p)); maximum(); system ( "pause" ); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具