单调队列+滑动窗口例题题解

单调队列解决滑动窗口问题 单调队列其实就是一个队列,只是使用了一点巧妙的方法使得队列中的元素全都是单调递增(或单调递减)的单调队列主要解决以下问题:给你一个数组window,已知其最值为A,如果给window中添加一个数B,那么比较一下A和B就可以立即算出新的最值;但如果要从window数组中减少一个数,就不能直接得到最值了,因为如果减少的这个数恰好是A,就需要遍历window中的所有元素重新寻找新的最值。针对这个问题我们可以用优先级队列解决吗?我们都知道优先级队列是一个特殊的队列,专门用来动态寻找最值得。 阅读详情

本文为博主原创文章,未经允许不得转载。如有问题,欢迎指正!

目录

 

单调队列简介

模板题: 洛谷   P1886 滑动窗口

用双端队列deque实现用单调队列求区间最大值(核心过程及代码模板):

完整代码:

做题小结:


单调队列简介

单调队列适用于快速求出一段区间最大值(最小值)的情况,以下讨论求最大值的问题:

在我看来,思路就是维护一个单调递减的队列:往队尾插入元素时,比较插入元素和队尾元素,依次删除所有比插入元素大的队尾元素,直到有元素大于插入元素或者队列为空时,将插入元素入队。队首元素就是当前区间的最大值,若对区间长度有要求,则在队首去掉已经不在区间里的元素。

模板题: 洛谷   P1886 滑动窗口

题目地址:https://www.luogu.com.cn/problem/P1886

题目详解:

因为求最大值和最小值的思想类似,故此处以求区间里的最大值为例:

依据前面对优先队列的描述,不难发现优先队列的实现中要在队尾插入元素,在队首或队尾删除元素。于是可以考虑用C++stl

中的双端队列deque来模拟整个过程。

用双端队列deque实现用单调队列求区间最大值(核心过程及代码模板):

struct elem{
 int id;       //下标
 int value;    //元素值
};
//定义结构体elem记录元素值和其对应的下标(下标值用于判断元素是否在当前区间)


vector<elem>V;
//定义vector<elem>V来存储所有元素值


deque<elem>maX;
//定义双端队列maX存储并更新维护这个单调递减的队列(单调队列)

 

//具体过程:
//遍历V中元素,在插入元素前除大于当前元素的队尾元素和不在当前区间的队首元素出队
  for(int i=0;i<n;i++){
         elem now=V[i];
  
     //去除大于当前元素的队尾元素
         while(!maX.empty()&&(now.value>=maX.back().value ) ){
         maX.pop_back();
         }


     //已经不在当前区间的队首元素出队:
        while(!maX.empty()&&(now.id-maX.front().id)>=a){
         maX.pop_front();
         }
  
     
        //将当前元素入队,并输出最大值
         maX.push_back(now);
         if(i+1>=a){
         write(maX.front().value);
         printf(" ");
           }
        }   

完整代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<deque>
   using namespace std;
    struct elem{
    	int id;
    	int value;
	};

   int read() {
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-') f=-f;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

  void write(int x) {
    if(x<0) {
        putchar('-');
        x=-x;
    }
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

	 int main(){
	 vector<elem>V;	
	 deque<elem>miN;
	 deque<elem>maX;
	 int n,a;
	 n=read();
	 a=read();
	    for(int i=0;i<n;i++){
	 	int v;
		v=read();
	    elem va;
	    va.id =i;
	    va.value=v;
		V.push_back(va);  
		 }
        for(int i=0;i<n;i++){
	  elem now=V[i];
	  while(!miN.empty()&&(now.value<=miN.back().value )){
          miN.pop_back();
		 }
	    while(!miN.empty()&&(now.id-miN.front().id)>=a){
		 miN.pop_front();
		 }
		  miN.push_back(now);
		 if(i+1>=a){
		 write(miN.front().value);
		 printf(" ");
	      }
           } 
        cout<<endl;
     

	for(int i=0;i<n;i++){
	   elem now=V[i];
	   while(!maX.empty()&&(now.value>=maX.back().value ) ){
	   maX.pop_back();
		 }
	    while(!maX.empty()&&(now.id-maX.front().id)>=a){
		 maX.pop_front();
		 }
		 maX.push_back(now);
	     if(i+1>=a){
	     write(maX.front().value);
	     printf(" ");
	       }
                 }    
          return 0;   
        }
        
        

[点击并拖拽以移动]
​

做题小结:

1.此题用C++的输入输出最后一组数据超时,copy来快速读入和输出的函数read()和write()函数就轻松AC了。

2.可以用back()函数获取deque的队尾元素

3.单调队列具体操作总结为:遍历元素,在插入元素前除大于当前元素的队尾元素和不在当前区间的队首元素出队。

4. 调试心得:某一次将maX.back()赋值给变量first代如while循环中,写成下面这样:

elem first=maX.back();

while(!maX.empty()&&(now.value>=first.value ) )     maX.pop_back();

在循环中尽量不用“中间变量”去替代一些会变化的值!如此处maX.back()就是变化的。

正确写法:   while(!maX.empty()&&(now.value>=maX.back().value ) )

上一篇博客:题解:数学考试(动态规划、前缀和)

【数据结构】单调栈和单调队列 详解+例题剖析 一.入门 P1440求m区间内的最小值 题目描述 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值。若前面的数不足m项则从第1个数开始,若前面没有数则输出0。 输入: 6 2 7 8 1 4 3 2 输出: 0 7 7 1 1 3 阅读详情

相关推荐

LeetCode 239. 滑动窗口最大值【c++/java详细题解】

目录1、题目2、思路3、c++代码4、java代码 1、题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 示例 1: 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1

林深不见鹿 的博客 2690

整数滑动窗口(acwing算法题C++)

题目 给定一个大小为n≤106 的数组。 有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。 你只能在窗口中看到k个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子: 该数组为[1 3 -1 -3 5 3 6 7],k为3。 窗口位置 最小值 最大值 [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 ...

falldeep的算法世界 1367

innovus实战攻略 | 用setUsefulSkewMode解锁时序优化的“隐藏技能”!

就像时序优化的“瑞士军刀”,参数虽多,但掌握了分类逻辑后,用起来其实很简单!如果你有更绝的用法,欢迎在评论区分享,大家一起卷起来!简单来说,它就是时序优化的“乾坤大挪移”。通过调整触发器的时钟到达时间,把关键路径的建立时间“借”给非关键路径,从而实现全局时序收敛。别急,这个命令就是你的“时序救星”!(工具最多只能借1.2ns的裕量,防止“借过头”导致新问题!这个参数能帮你兜底!(对关键路径“下死手”,确保优化到位!(设置上限,给工具套上“紧箍咒”!(直接跳过边界,避免优化反噬!(全局管理,防止“借过头”!

weixin_50820814的博客 1355

滑动窗口/单调队列

滑动窗口和单调队列是两种常见的数据结构和算法技巧,它们可以解决一些特定类型的问题。下面分别介绍它们的概念和作用:滑动窗口是一种用于处理数组(或列表)的算法技巧。它通常用于解决连续子数组问题,如找到数组中的最大或最小子数组。滑动窗口的大小和位置可以根据问题的要求调整。在处理问题时,窗口在数组中从左到右滑动,每次滑动一定的距离,然后在当前窗口内进行相关计算。 滑动窗口的优点是可以减少重复计算,降低时间复杂度。例如,在计算数组中的最大子数组和时,我们可以用滑动窗口避免每次都从头开始计算和。单调队列是一种特殊的数据

跑跑跑的博客 964

第3章 zynq MII转GMII的配置和EMIO UART0的配置

本文介绍了在Vivado工程中实现MII转GMII接口适配的过程,同时配置EMIO UART0接口。主要内容包括:修改PS IP核添加UART0接口,使用concat IP核进行信号整合,调整GMII信号引脚连接,添加约束文件定义引脚映射,并最终生成bit流文件。通过详细的操作截图和TCL约束代码,展示了从硬件配置到生成可编程文件的完整流程,为Zynq平台开发提供了实用参考。

qq_36517072的博客 903

S7-1200PLC期末复习题(第七章)

A.0 B.1 C.4 D.-4 A、CV = 0 B、CV = 1 C、CV < 4 D、CV >= 4A、0,0 B、3,0 C、1,1 D、3,1 A、0 B、1 C、先是1,再变为0 D、先是0,再变为1置位输出:常开触点M0.0闭合,Q0.0变为1状态并保存该状态,即使M0.0断开,Q0.0也保持1状态。 复位输出:常开触点M0.1闭合时,Q0.0变为0状态并保持该状态,即使M0.1断开,Q0.0也保持为0状态。 A、1 B、0 C、5 D、10RESET_BF指令需要两个参数,第一个是复位的位数

qq_52251819的博客 4420

单调队列(滑动窗口)

单调队列复习,别看了正经人看不懂我写的啥QwQ

m0_66640248的博客 1167

基于YOLOv11的手术器械计数系统:从数据集构建到Web应用部署

m2cai16-tool数据集:包含15种腹腔镜手术器械的标注图像Cholec80数据集:包含80个胆囊切除手术视频,标注了7种器械SurgicalTools数据集:包含超过10,000张手术器械图像,涵盖21类常见器械手术剪(Scissors)止血钳(Hemostat)持针器(Needle Holder)手术刀(Scalpel)镊子(Forceps)拉钩(Retractor)吸引器(Suction)

YOLO 396

【算法基础】滑动窗口+单调队列

1. 通常说给定一数组nums,让我们求一段子数组所满足的性质,如nums中最短之和大于target的子数组长度。 2. 求给定一子数组长度,让我们求子数组中元素的最值,还有就是求其各子数组之和或者积。

2301_77431942的博客 2811

ADS基础教程20 - 电磁仿真(EM)参数化仿真

一、引言二、参数化设置1.参数定义2.参数赋值3.创建EM模型和符号四、总结1)在Layout视图,菜单栏中选中EMComponent2)在弹出的参数编辑框中,采用标称/扰动()设计。使用子网(Subnetwork)参数。这些方法是互斥的,在为单个组件定义参数时不能将它们组合起来。标称/扰动(Nominal/Perturbed)参数使用平面化布局场景,并且只包含端口和原始图形形状(如多边形、矩形和圆形)时定义。

XZ_ZC的博客 4029

【FISCO-BCOS】 八、ubuntu配置Java环境

ubuntu配置Java环境需根据自己的java版本号进行细节修改,本文以jdk11.0.18版本为例。ps:通过此法还可以查看java安装路径,但必须是环境配置成功的情况下才能使用。二、添加Java环境路径。四、检查java环境设置。

naihe_fish的博客 4309

【数据结构】单调队列

单调队列是一个双端队列。单调队列的特点是队列中的元素按照一定的单调性排列。在插入新元素时,如果新元素破坏了当前的单调性,则在队尾删除一部分元素,直到满足单调性要求,以维护队列单调性。单调队列的典型应用是在滑动窗口中寻找最大/最小值的问题。

miao_tofu的博客 1074

SAP采购申请审批策略配置简介

SAP采购申请审批策略配置简介 1、CT04创建特征

我小时候很黑的博客 8161

JAVA算法练习题day9

题解各个方法中,单调队列的做法最优,先掌握这个,其他模型到了经典例题时候再学(大根堆之类的)。今天19.02就完成了算法题的学习和练习。双头队列(单调队列),他一步一步分析的思路值得学习模仿。

illuosion7的博客 173

华为OD机试 - 整型数组按照个位数排序(Java 双机位C卷 100分)

华为OD机试 双机位C卷题库疯狂收录中,刷题。

学Java,找哪吒 349

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

单调队列 + 例题:洛谷P2032 扫描 题解

单调队列单调队列是一种具有单调性的结构,它可以用来求最大值最小值等操作,它是一种特殊的双端队列,它保持队列中元素的单调性。单调队列可以在O(1)的时间复杂度内求得队列中的最大值或最小值。在单调队列中,队列中的元素按照一定的顺序排列,并且队列中的元素满足某种单调性。常见的单调队列有单调递增队列和单调递减队列。在单调递增队列中,队列中的元素按照递增的顺序排列;在单调递减队列中,队列中的元素按照递减的顺序排列。单调队列常用于求解滑动窗口问题,可以高效地获取滑动窗口内的最大值或最小值。

zsrWC的博客 1140

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

单调队列详解,附 P1886 滑动窗口、P9905 AN2DL 题解

这道题就是单调队列,只不过增加了一维而已,还是可以轻松搞定。

2301_76224755 的博客,一只 OIER,只会 C++。 2742

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

滑动窗口 单调队列

洛谷 单调队列模板题链接 参考题解 单调队列有两个性质 队列中的元素其对应在原来的列表中的顺序必须是单调递增的。 队列中元素的大小必须是单调递*(增/减/甚至是自定义也可以) 单调队列与普通队列不一样的地方就在于单调队列既可以从队首出队,也可以从队尾出队。 那么我们应该怎样实现单调队列呢? 就拿样例来谈谈,设以最小的为标准。 8 3 1 3 -1 -3 5 3 6 7 下文...

陈颜的博客 5299

P1886 滑动窗口 /【模板】单调队列【题解】

摘要 本文介绍了滑动窗口问题的单调队列解法。题目要求在一个长度为n的序列中,找出所有大小为k的滑动窗口的最小值和最大值。由于暴力解法时间复杂度为O(n^2)无法通过,采用单调队列优化。维护两个双端队列,分别处理最小值和最大值:对于最小值,保持队列单调递增;对于最大值,保持队列单调递减。每次窗口滑动时,移除超出范围的元素,并确保队列单调性。最终每个窗口的最值即为队首元素。该算法时间复杂度为O(n),适用于大规模数据。文章提供了C++实现代码,使用STL的deque容器,并解释了关键操作步骤。

cyx20091026的博客 820

洛谷:P1886 滑动窗口 /【模板】单调队列 Java题解

这道题目要求我们处理一个长度为n的序列,使用一个大小为k的滑动窗口从左向右移动,每次移动后输出窗口中的最小值和最大值。这是一个典型的滑动窗口问题,可以使用单调队列高效解决。这种方法利用单调队列高效维护了滑动窗口的最小值和最大值,适用于大规模数据。• 空间复杂度:O(n),最坏情况下队列中存储n个元素。• 时间复杂度:O(n),每个元素最多入队和出队一次。

Java爱好者,热爱分享,信仰开源! 566

单调队列【总结】

一、基本概念 单调队列是指:单调递增或单调递减的队列。所以它也有如下几个性质: 1.队列中的元素在原来的列表中的位置是由前往后的(随着循环顺序入队)。 2.队列中元素的大小是单调递增或递减的。 3.从队尾入列,队首或队尾出列 时间复杂度:O(N) 二、例题 1.最大子序和(dp+单调队列优化) 题目描述 输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当m=2或m=3时,S=5+1=6 输入 第一行两

算法小猪的博客 2147

【双端队列】【单调队列】总结 + 滑动窗口题解

当新的数据进入窗口时,旧的数据会从另一端移出,双端队列可以很好的模拟滑动窗口的更新过程。2.单调队列特点:单调队列中的元素按照一定顺序排列,常见的是单调递增或单调递减。b.双端队列常用于 需要高效处理双向数据流或需要快速访问两端元素的场合。,例如求最大值、最小值,单调队列解决滑动窗口的复杂度为O(n)。2.双端队列常用函数。3.双端队列使用场景。三、滑动窗口 模板题。

2403_86562178的博客 674

洛谷 P1886 滑动窗口 (单调队列) 题解

滑动窗口 (单调队列) 题解 洛谷 P1886 题目 有一个长为 nnn 的序列 aaa,以及一个大小为 kkk 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。 例如: TheTheThe arrayarrayarray isisis [1,3,−1,−3,5,3,6,7], andandand kkk=3。 输入 输入一共有两行,第一行有两个正整数 nnn,kkk。 第二行 nnn 个整数,表示序列 aaa 输出 输出共两行,第一行为每次窗口滑动的最小值

Y的博客 363

单调队列【高效版】

🐬初学一门技术时,总有些许的疑惑,别怕,它们是我们学习路上的点点繁星,帮助我们不断成长。🐟文章粗浅,希望对大家有帮助!🦄参考文章滑动窗口(单调队列)滑动窗口(单调队列)

仰望天空,妳我亦是行人. 1114

P1886 滑动窗口 /【模板】单调队列 题解

P1886 滑动窗口 /【模板】单调队列 题解

yaosichengalpha的博客 671

单调队列优化&&P1886 滑动窗口题解

单调队列: 顾名思义,就是队列中元素是单调的(单增或者单减)。 在某些问题中能够优化复杂度。 在dp问题中,有一个专题动态规划的单调队列优化,以后会更新(现在还是太菜了不会)。 在你看到类似于滑动定长度区间的类似问题时可以考虑单调队列优化。 就像这道题:P1886 滑动窗口。 一道模板题。那么我们从题目入手讲解。 首先,你看完了题。。(??) 1.暴力 ...

weixin_30438813的博客 175
上一篇: 题解:数学考试(动态规划、前缀和)
下一篇: leetcode 338 比特位计算(位运算)
准图灵奖得主
博客等级 码龄8年 355粉丝 135原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值