单调队列及滑动窗口(STL)
单调队列版题#
不错的教程:https://zhuanlan.zhihu.com/p/422908736
P1440 求m区间内的最小值 - 洛谷
这一题理解了好久,不过理解了这题,滑动窗口也可以马上写出
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<deque> using namespace std; const int maxsize = 2000010; int n, m; struct node { int val;//值 int pos;//下标 }A[maxsize]; deque<node> min_Q; int min_que[maxsize];//存储答案的数组 int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++){ scanf("%d",&A[i].val);//输入值 A[i].pos = i - 1;//输入下标 } min_que[0] = 0;//若前面没有数则输出 0。所以第一项输出0 for (int i = 1; i < n; i++){//从1到n-1枚举 while (!min_Q.empty() && min_Q.back().val >= A[i].val) {//要求进入的数字必须比目前已有最大的数字小 min_Q.pop_back(); } min_Q.push_back(A[i]);//当i==1时min_Q是空的,所以直接将A[1]塞入,对应A[1].val==7,A[1].pos==1 while (!min_Q.empty() && min_Q.front().pos < i - m) {//前端第一个下标小于i-m(即小于(当前位数-范围位数)的全踢了 min_Q.pop_front(); } min_que[i] = min_Q.front().val;//最前端就是答案 } for (int i = 0; i < n; i++)//输出答案 printf("%d\n", min_que[i]); return 0; }
滑动窗口/单调队列版题#
贴一个洛谷题解对样例的模拟
P1886 滑动窗口 /【模板】单调队列 - 洛谷
#include<iostream> #include<deque> #include<algorithm> using namespace std; struct node{ int val,pos;//值与下标 }arr[20000010];//输入数组 deque<node>Q;//单调队列 int ans_min[20000010];//记录最小值 int ans_max[20000010];//记录最大值 int n,m; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&arr[i].val);//输入数据 arr[i].pos = i-1;//记录下标必须-1 } for(int i=1;i<=n;i++){//判断最小 if(Q.empty()) Q.push_back(arr[i]);//如果队列为空直接插入 else if(!Q.empty()&&arr[i].val<=Q.front().val){//如果arr[i]小于队列中最小值,直接清空队列再加入 Q.clear();//清空 Q.push_back(arr[i]);//加入 } else if(!Q.empty()&&arr[i].val>Q.front().val){//如果arr[i]大于队列中最小值 while(Q.back().val>arr[i].val){//就把所以大于arr[i]的元素踢出队列 Q.pop_back();//踢出 } Q.push_back(arr[i]);//插入到一个合适位置保证单调 } while(Q.front().pos<i-m&&!Q.empty()){//如果队前元素过气,踢出 Q.pop_front(); } if(i>=m)ans_min[i]=Q.front().val;//队前元素为最小值 } for(int i=1;i<=n;i++){//判断最大 if(Q.empty()) Q.push_back(arr[i]);//如果队列为空直接插入 else if(!Q.empty()&&arr[i].val>=Q.front().val){//如果arr[i]大于队列中最小值,直接清空队列再加入 Q.clear();//清空 Q.push_back(arr[i]);//加入 } else if(!Q.empty()&&arr[i].val<Q.front().val){//如果arr[i]小于队列中最小值 while(Q.back().val<arr[i].val){//就把所以小于arr[i]的元素踢出队列 Q.pop_back();//踢出 } Q.push_back(arr[i]);//插入到一个合适位置保证单调 } while(Q.front().pos<i-m&&!Q.empty()){//如果队前元素过气,踢出 Q.pop_front(); } if(i>=m)ans_max[i]=Q.front().val;//队前元素为最大值 } for(int i=m;i<=n;i++) printf("%d ",ans_min[i]);//输出最小值 puts(" ");//空行 for(int i=m;i<=n;i++) printf("%d ",ans_max[i]);//输出最大值 return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示