题目链接

https://www.luogu.com.cn/problem/P1886

题目大意

有一个长为 \(n\) 的序列 \(a\) ,以及一个大小为 \(k\) 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

题目解析

使用 \(C++\) 的 \(STL\) 库中的 \(deque\) 。

以窗口最小值为例,设该双端队列为 \(Q\) ,其队头则为每一次的答案:

首先,保证 \(Q\) 中均为未过期的值(即, \(Q\) 中元素均在窗口中)。

然后,比较 \(Q\) 的队头与新加入的值 \(a[i]\) 。

  • 若 \(a[i]\) 更小,则可以清空队列,加入 \(a[i]\) (因为此时 \(a[i]\) 不但最新,而且最小)。
  • 若原队头更小,将 \(a[i]\) 加入队尾,但是在加入之前,确保 \(a[i]\) 大于队尾(如果 \(a[i] \leq\) 队尾,则明显更优,队尾就废弃直接弹出了)。

这样,就可以保证答案的正确性了。

其次,我们来考虑复杂度,队列中长度总不大于窗口大小,每一个元素只进出一次, \(a[i]\) 总比较次数不超过 \(n\) 次,因此总的时间复杂度为 \(O(n)\) 。

最大值同理。

参考代码

#include <bits/stdc++.h>
using namespace std;
deque <pair <int, int> > Q;
vector <int> a; int main()
{
int n, k, x;
scanf("%d%d", &n, &k);
for (int i = 0; i < n; ++i) {
scanf("%d", &x);
a.push_back(x);
}
/*求滑动窗口最小值*/
for (int i = 0; i < n; ++i) {
if (!Q.empty()) {
if (a[i] <= Q.front().first) {Q.clear(); Q.emplace_front(a[i], i);}
else {
while (a[i] <= Q.back().first) Q.pop_back();
Q.emplace_back(a[i], i);
}
}
else Q.emplace_back(a[i], i);
if (i >= k-1) {
while (!Q.empty() && Q.front().second < i-k+1) Q.pop_front();
if (!Q.empty()) printf("%d ", Q.front().first);
}
}
putchar('\n');
Q.clear();
/*求滑动窗口最大值*/
for (int i = 0; i < n; ++i) {
if (!Q.empty()) {
if (a[i] >= Q.front().first) {Q.clear(); Q.emplace_front(a[i], i);}
else {
while (a[i] >= Q.back().first) Q.pop_back();
Q.emplace_back(a[i], i);
}
}
else Q.emplace_back(a[i], i);
if (i >= k-1) {
while (!Q.empty() && Q.front().second < i-k+1) Q.pop_front();
if (!Q.empty()) printf("%d ", Q.front().first);
}
}
putchar('\n');
return 0;
}

感谢支持!

【模板】滑动窗口最值(单调队列)/洛谷P1886的更多相关文章

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

    题面 单调队列模板题. 单调队列可以从队首和队尾出队. 队列中的元素大小具有一定的顺序. 具体可参考这一篇题解 #include <bits/stdc++.h> #define itn i ...

  2. 【洛谷P1886】滑动窗口——单调队列

    没想到啊没想到,时隔两个月,我单调队列又懵了…… 调了一个小时,最后错在快读,啊!!!!(不过洛谷讨论真好啊,感谢大佬!) 考前就不推新东西了,好好写写那些学过的东西 题目点这里(我就不粘了自己点一下 ...

  3. [洛谷P1886]滑动窗口 (单调队列)(线段树)

    ---恢复内容开始--- 这是很好的一道题 题目描述: 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口. 现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的 ...

  4. 洛谷 P1886 滑动窗口(单调队列)

    题目链接 https://www.luogu.org/problemnew/show/P1886 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始 ...

  5. 洛谷 P1886 滑动窗口(单调队列)

    嗯... 题目链接:https://www.luogu.org/problem/P1886 首先这道题很典型,是标准的单调队列的模板题(也有人说单调队列只能解决这一个问题).这道题可以手写一个队列,也 ...

  6. 关于双端队列 deque 模板 && 滑动窗口 (自出)

    嗯... deque 即为双端队列,是c++语言中STL库中提供的一个东西,其功能比队列更强大,可以从队列的头与尾进行操作... 但是它的操作与队列十分相似,详见代码1: 1 #include < ...

  7. 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

    To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...

  8. 【洛谷P1886】滑动窗口

    滑动窗口 [题目描述] 有N个数字,以及一个大小为k的窗口.现在这个窗口从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 思路: k<=N<=1000000,暴 ...

  9. 洛谷 P1886 滑动窗口

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

随机推荐

  1. 热身训练3 Palindrome

    Palindrome 简要题意:  我们有一个字符串S,字符串的长度不超过500000. 求满足S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)(n≥2)的子串个数.  分析: 我们能通过简 ...

  2. 热身训练1 Blood Cousins Return

    点此看题 简要题面: 一棵树上有n个节点,每个节点有对应的名字(名字可重复). 每次询问,求深度比$vi$多$ki$的$vi$的儿子中,有多少种名字 分析: Step1: 我们可以懂$DFS$轻松找到 ...

  3. 用C++实现的数独解题程序 SudokuSolver 2.7 及实例分析

    引言:一个 bug 的发现 在 MobaXterm 上看到有内置的 Sudoku 游戏,于是拿 SudokuSolver 求解,随机出题,一上来是个 medium 级别的题: 073 000 060 ...

  4. 一步一步学ROP之linux_x86篇(蒸米spark)

    目录 一步一步学ROP之linux_x86篇(蒸米spark) 0x00 序 0x01 Control Flow Hijack 程序流劫持 0x02 Ret2libc – Bypass DEP 通过r ...

  5. 微信小程序API接口封装

    @ 目录 一,让我们看一下项目目录 二,让我们熟悉一下这三个文件目的(文件名你看着办) 三,页面js中如何使用 今天的API的封装,我们拿WX小程序开发中,对它的API (wx.request)对这个 ...

  6. Linux网卡bond模式

    Bond模式 交换机配置 mode=0 balance-rr 轮询均衡模式 LACP mode on 强制链路聚合 mode=1 active-backup 主备模式 无 mode=2 balance ...

  7. 对于multitaper多窗口谱估计的理解及步骤 (对应matlab中pmtm函数)谱减法相关

    对于多窗口谱估计的理解 目录 对于多窗口谱估计的理解 0. 缘起 1. PMTM 含义 2. 与我们常用的周期谱估计的区别 3. 计算过程 5. 多窗/单窗谱估计结果对比 6. 程序如何生成多窗 - ...

  8. ELK集群之filebeat(6)

    filebeat工作原理 ilebeat是本地文件的日志数据采集器. 作为服务器上的代理安装,Filebeat监视日志目录或特定日志文件,tail file,并将它们转发给Elasticsearch或 ...

  9. 性能工具之代码级性能测试工具ContiPerf

    前言 做性能的同学一定遇到过这样的场景:应用级别的性能测试发现一个操作的响应时间很长,然后要花费很多时间去逐级排查,最后却发现罪魁祸首是代码中某个实现低效的底层算法.这种自上而下的逐级排查定位的方法, ...

  10. Git基本教程

    git的发展 Git 两周开发 Linus开发,主要是为了管理大量人员维护代码 Git分布式版本控制系统 基本命令 history:查看之前用过的命令 vimtutor git配置 查看配置 git ...