首页 > 其他分享 >单调队列详解

单调队列详解

时间:2023-01-19 16:23:52浏览次数:53  
标签:putchar 队列 ll while 详解 单调 define

简介

单调栈和单调队列都是思维难度比较大的数据结构,但只要想明白了就会觉得很简单。
要理解单调队列,首先得明白“单调”是指它存储的内容单调,而不是指它简单。

实现

模板题(AcWing.154

题目描述

给定一个大小为 \(n≤10^6\) 的数组。
有一个大小为 \(k\) 的滑动窗口,它从数组的最左边移动到最右边。
请输出滑动窗口位于每个位置时,窗口中的最大值和最小值。

样例

in:

8 3
1 3 -1 -3 5 3 6 7

out:

-1 -3 -3 -3 3 3
3 3 5 5 6 7

单调队列实现

思路

先看题目给的表:

窗口位置 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3] 5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7

首先考虑用暴力怎么做,一定要先思考一下暴力!不然很难理解单调队列!(优化后的暴力)

先计算最小值。

这些数可以看做是一个队列,队头是 \(l\) ,队尾是 \(r\) ,每次滑动窗口,都是 \(l+1\) , \(-1\) 。
显然很多窗口中都有一些我们肯定不需要的数。

考虑优化。

可以发现,在如果队列中存在 \(x<y\) 且 \(a_x≥a_y\) ,那么 \(a_x\) 就没用了。因为只要 \(a_y\) 在队列中,\(a_x\) 就永远不可能输出,而且 \(a_y\) 在 \(a_x\) 后面,会比 \(a_x\) 的出栈时间晚(通俗点讲就是 \(a_y\) 比 \(a_x\) 活得久)。

这样一来,这个序列就成了单调递减的了,每次查询输出右端点 \(a_r\) 就行了。

计算最大值同理。

用单调队列维护后会得到单调递增的一个队列,每次查询也是输出右端点 \(a_r\) 。

代码

#include <bits/stdc++.h>
#define ll long long
#define rll register ll
#define cll const ll
#define N 1000005
using namespace std;
inline ll read()
{
    rll x=0;bool f=1;static char c=getchar();
    while(!isdigit(c)){if(c=='-') f=0;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return (f==1)?x:-x;
}
inline void write(ll x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+48);
}
ll n=read(),k=read(),l,r=-1,a[N],q[N];
int main()
{
    for(ll i=0;i<n;i++) a[i]=read();
    for(ll i=0;i<n;i++)
    {
        if(l<=r&&i-k+1>q[l]) l++;
        while(l<=r&&a[i]<=a[q[r]]) r--;
        q[++r]=i;
        if(i>=k-1) write(a[q[l]]),putchar(' ');
    }
    putchar('\n');l=0,r=-1;
    for(ll i=0;i<n;i++)
    {
        if(l<=r&&i-k+1>q[l]) l++;
        while(l<=r&&a[i]>=a[q[r]]) r--;
        q[++r]=i;
        if(i>=k-1) write(a[q[l]]),putchar(' ');
    }
    return 0;
}

标签:putchar,队列,ll,while,详解,单调,define
From: https://www.cnblogs.com/wangxuzhou-blog/p/17061711.html

相关文章

  • DBNet源码详解
    参考项目:https://github.com/WenmuZhou/DBNet.pytorch标签制作制作thresholdmap标签make_border_map.py程序入口if__name__=='__main__'if__name__=='__main......
  • 一文搞定大数据消息队列Kafka
    文章目录​​1.JMS+AMQP核心知识​​​​1.1.什么是MQ中间件​​​​1.2.使用场景​​​​1.3.JMS消息服务和和常见核心概念​​​​2.分布式流处平台Kafka核心概念​​​​......
  • 【并发编程】ThreadLocal详解
    文章目录​​1.ThreadLocal简介​​​​2.ThreadLocal的简单使用​​​​3.ThreadLocal的实现原理​​​​4.ThreadLocal不支持继承性​​​​5.InheritableThreadLocal支持......
  • 数据结构-优先队列与栈
    数据结构-优先队列与栈今天不多BB,直接讲2个数据结构!优先队列(priorityqueue)优先队列没什么好说的,和队列相似,同样遵循FIFO,但优先队列中的数据按升序或者降序排列,定义如......
  • OpenCV Mat类详解
    1.Mat类常用成员函数和成员变量        由于Mat类使用的非常广泛,使用的形式也非常之多,这里只对较为常用的成员函数和成员变量做出了整理;1.1构造函数(1)默认构......
  • 分块入门详解(比较全面)
    最近写了几个分块,顺便做一下笔记。什么是分块分块是一种数据结构。。有许多数据结构都是\(\mathrm{log}\)数据结构,比如线段树,树状数组等等。他们复杂度优秀,但是都是树......
  • pikachu-CSRF跨站请伪造通关详解
    pikachu-CSRF跨站请伪造通关详解一、getburp抓包修改信息页面,可以看到请求的url修改的数据都在url中,我们可以尝试在url中修改,之后再去访问url此时的数据内容:将url中......
  • 初探attention—attention原理和代码详解
    attention在正式开始探索attention之前,首先了解一下seq2seq。循环神经网络只能将一个序列信号转换为定长输出,但Seq2Seq可以实现一个序列信号转化成一个不定长的序列输出,因......
  • 单调栈详解
    简介单调栈和单调队列都是思维难度比较大的数据结构,但是比较幸运,这些数据结构能出的题不多,只有几个板子。要理解单调栈,首先得明白“单调”是只它存储的内容单调,不是说它......
  • HTML5绘图基础_09_绘制弧线详解
    ​​CanvasRenderingContext2D​​​​.arc()​​ 是Canvas2DAPI绘制圆弧路径的方法。圆弧路径的圆心在 (x,y) 位置,半径为 r ,根据anticlockwise (默认为顺时针)指......