单调队列

本文介绍了单调队列,即元素呈单调关系,队首与队尾可出队、队尾可入队。阐述了插入和获取最优值等常用操作,给出操作流程示例。最后通过一道求定长连续子区间最值的题目帮助理解,并给出了相关代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

队列就是一排数,那么显而易见,单调队列就是元素之间呈单调关系,可以是单调递增的关系,也可以是单调递减的关系,而且队首与队尾都可以进行出队操作,而只有队尾可以进行入队操作。

常用操作:

1. 插入:若新元素插入队尾会破坏队列的单调性,就删除队尾元素,直到插入后不破坏队列的单调性。

2. 获取最优值: 若需要得到最大,最小值,一般可以通过直接访问队首与队尾的元素得到。

操作流程:

如一个队列:(1,3,2,1,5,6)

得到单调队列的过程:

首先第一个元素,1入队:得到1

再得到第二个元素,3入队: 得到1,3

2入队,但因为2小于3,所以3弹出,得到:1,2

1入队,又因为1小于2,所以3弹出,得到:1,1

5入队,得到:1,1,5

6入队,得到:1,1,5,6

所以1,1,5,6就是最终的单调队列

这就是队列的实现原理,以通俗易懂的方式呈现出来。

最后列道题帮助记忆:

给定一个长度为n的数列,求长度为k的定长连续子区间{a1,a2,a3,a4,…,ak-1,ak}{a2,a3,…,ak,ak+1}……中每个区间的最大值和最小值。

代码:

#include <cstdio>
#include <cstring>
#include<iostream>
#define MAXN 80050
#define LL long long
using namespace std;
LL q[MAXN];
int main()
{
    int n;
    scanf("%d",&n);
    LL a;
    LL ans=0;
    int rear=-1,front=0;
    for(int i=0;i<n;i++){
        scanf("%I64d",&a);
        while(rear>=front&&q[rear]<=a)rear--;     //看最后一位数与下一位入队的数谁大,直到新入队的数比前一位大为止,这是队列的核心代码。
        q[++rear]=a;           //将数放入队列
        ans+=rear;               //记录下长度
    }
cout<<ans<<endl;
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值