单调队列经典题目

扫描 - 洛谷

#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
int x;
struct sd
{
    int pos,val; //存储编号和大小
}a[N];
deque<sd> que;
int n,k;
vector<int>ans;
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        a[i].pos=i;
        a[i].val=x;
    }
    for(int i=1;i<=n;i++)
    {
        while(!que.empty()&&que.back().val<=a[i].val)
            que.pop_back();
        que.push_back(a[i]);
        while(!que.empty()&&que.front().pos<=i-k)
            que.pop_front();
        if(i>=k)ans.push_back(que.front().val);
    }
    for(int i:ans)
        cout<<i<<endl;
    return 0;
}

求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;
inline int rd()
{
    int data = 0;
    int f = 1;
    char ch = getchar();
    while(ch < '0'||ch > '9')
    {
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0'&&ch <= '9')
    {
        data = (data<<3) + (data<<1) + ch - '0';
        ch = getchar();
    }
    return f * data;
}
int min_que[maxsize];
int main()
{
    n = rd(),m = rd();
    for(int i = 1;i <= n;i++)
    {
        A[i].val = rd();
        A[i].pos = i ;
    }
    min_que[0] = 0;
    for(int i = 1;i < n;i++)
    {
        while(!min_Q.empty()&&min_Q.back().val >= A[i].val)
            min_Q.pop_back();
        min_Q.push_back(A[i]);
        while(!min_Q.empty()&&min_Q.front().pos <= 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]);

}

滑动窗口 /【模板】单调队列 - 洛谷

#include<bits/stdc++.h>
using namespace std;
int x;
struct sd
{
    int num,val; //存储编号和大小
};
deque<sd> que;//从大到小
deque<sd> que1;//从小到大
int add[3][1000005]; //用以存储答案的----见代码
int main()
{
    int n,m,k,cnt=1;
    cin>>n>>k;
    sd rr;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);  //输入
        rr.num=i-1; rr.val=x;  //赋值
        while(!que.empty()&&x>=que.back().val)
        que.pop_back();  //单调队列的操作,以保证单调
        while(!que1.empty()&&x<=que1.back().val)
        que1.pop_back();
        que.push_back(rr); //压入队列
        que1.push_back(rr);//同上
        while(i-k>que.front().num)  //T掉不在范围内的
        que.pop_front();
        while(i-k>que1.front().num)
        que1.pop_front(); //同上
        if(i>k-1)
        {
            add[0][cnt]=que.front().val;
            add[1][cnt]=que1.front().val;
            cnt++;
        } //存答案
    }
    for(int i=1;i<cnt;i++)
    printf("%d ",add[1][i]);
    printf("\n");
    for(int i=1;i<cnt;i++)
    printf("%d ",add[0][i]);  //输出
    return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值