单调队列版题

不错的教程: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 滑动窗口 /【模板】单调队列 - 洛谷
单调队列及滑动窗口(STL)

#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;
}