当前位置:首页 > 技术分析 > 正文内容

CSP-S 提高篇 单调队列,宫斗续篇

ruisui881个月前 (05-16)技术分析18

1单调队列 算法原理


  1. 单调队列是一种特殊的队列,它维护队列中的元素始终保持单调性(递增或递减)。在滑动窗口最大值问题中,我们使用单调递减队列
  2. 队列中存储的是元素的索引而非元素值本身(在可视化中,我们同时显示索引和对应的值)
  3. 队列头部始终是当前窗口中的最大值索引
  4. 当新元素进入窗口时,从队尾移除所有小于新元素的值(它们不可能成为未来窗口的最大值)
  5. 当窗口滑动时,检查队首元素是否仍在窗口内,如果不在则将其移除


2滑动窗口


题目分析

单调队列模板题。

如果找滑动窗口最小值,当前元素如果比队列中已有元素都要小,那么这些元素都要出队,因为当前元素不仅更年轻、更符合要求,而且,生命周期更长。

参考程序

#include<bits/stdc++.h>
usingnamespacestd;


constint N = 1e6 + 10;


int n, k;
int a[N], q[N];


intmain(){


  cin >> n >> k;
  for(int i = 1; i <= n; i++) cin >> a[i];


  int hh = 0, tt = -1;


  for(int i = 1; i <= n; i++){
    if(hh <= tt && i - k + 1 > q[hh]) hh++;
    while(hh <= tt && a[q[tt]] >= a[i]) tt--;
    q[++tt] = i;
    if(i >= k)
      cout << a[q[hh]] << " ";
  }


  cout << endl;


  hh = 0, tt = -1;


  for(int i = 1; i <= n; i++){
    if(hh <= tt && i - k + 1 > q[hh]) hh++;
    while(hh <= tt && a[q[tt]] <= a[i]) tt--;
    q[++tt] = i;
    if(i >= k)
      cout << a[q[hh]] << " ";
  }


  return0;
}


3扫描



题目分析

单调队列基础模板题,同上一题。

参考程序

#include <bits/stdc++.h>
usingnamespace std;


const int N = 2e6 + 10;


int n, k;
int a[N];


int q[N], hh = 0, tt = -1;


int main() {


    cin >> n >> k;


    for(int i = 1; i <= n; i++) cin >> a[i];


    for(int i = 1; i <= n; i++){
        if(hh <= tt && i - k + 1 > q[hh]) hh++;
        while(hh <= tt && a[q[tt]] <= a[i]) tt--;
        q[++tt] = i;
        if(i >= k)
            cout << a[q[hh]] << endl;
    }


  return0;
}




4质量检测



题目分析

单调队列基础模板题,同上一题。

参考程序

#include <bits/stdc++.h>
usingnamespace std;


const int N = 1e5 + 10;


int n, k;
int a[N];


int q[N], hh = 0, tt = -1;


int main() {


    cin >> n >> k;


    for(int i = 1; i <= n; i++) cin >> a[i];


    for(int i = 1; i <= n; i++){
        if(hh <= tt && i - k + 1 > q[hh]) hh++;
        while(hh <= tt && a[q[tt]] >= a[i]) tt--;
        q[++tt] = i;
        if(i >= k)
            cout << a[q[hh]] << endl;
    }


  return0;
}


4求m区间内的最小值



题目分析

单调递增队列 O(n)

维护结构

  • 用一个队列存“下标”,并保持其对应值单调递增。
  • 队头永远是窗口最小值的下标。
  • 队列大小不固定,但下标始终在当前滑窗范围内。


参考程序

#include<bits/stdc++.h>
usingnamespacestd;


constint N = 2e6 + 10;
int n, m;
int a[N];
int q[N], hh = 0, tt = -1;   


intmain(){


    cin >> n >> m;
    for (int i = 1; i <= n; ++i) cin >> a[i];


    for (int i = 1; i <= n; ++i) {
        // 1) 弹掉已滑出窗口的元素 —— 只可能在队头
        while (hh <= tt && q[hh] < i - m) hh++;


        // 2) 输出答案(窗口里无元素则输出 0)
        if (hh <= tt) cout << a[q[hh]] << endl;
        else  cout << 0 << endl;


        // 3) 维护单调递增队列(最小值在前)
        while (hh <= tt && a[q[tt]] >= a[i]) tt--;
        q[++tt] = i;      // 把当前下标 i 插到队尾
    }
    return0;
}

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/4103.html

标签: js 队列
分享给朋友:

“CSP-S 提高篇 单调队列,宫斗续篇” 的相关文章

gitlab简单搭建与应用

一、gitlab1、简介GitLab是利用Ruby on Rails一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。与Github类似,GitLab能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历...

迁移GIT仓库并带有历史提交记录

迁移git仓库开发在很多时候,会遇到一个问题。GIT仓库的管理,特别是仓库的迁移。我需要保留已有的历史记录,而不是重新开发,重头再来。我们可以这样做:使用--mirror模式会把本地的分支都克隆。// 先用--bare克隆裸仓库 git clone git@gitee.com:xxx/testApp...

使用cgroup限制进程资源

这里使用containerd项目中的cgroup包来实现进程资源限制。先写一个耗费一个CPU并且一秒增加10m内存的测试进程package mainimport ( "fmt" "math/rand" "time")func main() { go f...

el-table内容\n换行解决办法

问题请求到的数据带有换行符 '\n'但页面展示时不换行statusRemark: "\"1、按期完成计划且准确率100%,得100分;\n2、各项目每延误1天,扣1分;每失误1次或者员工投诉1次,扣3分,失误层面达到公司级影响较大的,该项绩效分数为0\"\n&...

慕课 SpringBoot2.X+Vue+UniAPP,全栈开发医疗小程序

本课程以业务驱动技术栈,打造业务相对完整的掌上医疗小程序,解决大家没有好的毕设项目或者求职项目的困境。本课程案例采用前后端分离架构,业务功能完善(既有WEB管理端,也有移动用户端),界面美观,无需艰涩的技术也能做出亮眼的作品。SpringBoot2.X+Vue+UniAPP,全栈开发医疗小程序 |...

揭秘SpringBoot的魔法:20个注解让你的应用飞起来

在Java开发的世界里,SpringBoot以其强大的功能和简...