关于双端队列 deque 模板 && 滑动窗口 (自出)
嗯...
deque 即为双端队列,是c++语言中STL库中提供的一个东西,其功能比队列更强大,可以从队列的头与尾进行操作...
但是它的操作与队列十分相似,详见代码1:
- 1 #include <cstdio>
- 2 #include <iostream>
- 3 #include <deque>
- 4 //实际上,引用queue头文件也可以,里面包含了deque头文件
- 5
- 6 using namespace std;
- 7
- 8 deque<int> dq; //定义一个储存整型变量的双端队列dq
- 9
- 10 int main() {
- 11 dq.push_back(1); //从队列后插入,此时dq:1 (下同)
- 12 dq.push_back(2); //1,2
- 13 dq.push_front(1); //从队列前插入, 1,1,2
- 14 dq.push_front(2); //2,1,1,2
- 15 cout << dq.front() << endl; //输出队首元素,结果为2
- 16 cout << dq.back() << endl; //输出队尾元素,结果为2
- 17 dq.pop_front(); //弹出队首元素 1,1,2
- 18 dq.pop_back(); //弹出队尾元素 1,1
- 19 dq.clear(); //清空操作
- 20 if (dq.empty()) cout<<"队列已空!"<<endl; //判断队列是否为空
- 21 cout << dq.size() << endl; //结果为0,即输出队列中元素个数
- 22 return 0;
- 23 }
deque 模板
下面便是一个双端队列的模板题....先看题面:
滑动窗口求最值
题目描述:
在一个长度为n的整数序列上有一个长度为k的滑动窗口,求滑动窗口内的最大值。
输入输出:
输入n,k (n <= 10000,k <= n)
输出第_个滑动窗口以及此滑动窗口中的最大值...
题目解析:
就是在一个序列上对于每个长度为k的区间,求区间内的最值。
一种朴素的做法是,枚举区间起点,再自此向后比较k个元素,找出最值,这样的复杂度是O(nk)的。
还有一种不错的做法是利用单调队列。不妨假设我们已经得到了一个单调队列,他维护了当前的滑动窗口,显然,队首元素就是窗口内的最值。现在再来考虑如何用单调队列维护滑动窗口(以最大值为例,队列则为单调递减的,队首元素为窗口内的最大值):
我们遍历序列的每个元素,当队列为空时,肯定要加入队列;队列不为空,就要先从队尾弹出较小的元素,再加入,保证队列单调(这里有一个有趣的类比,也是滑动窗口的主要思想:如果一位OIer比你年轻还比你强,那你就没法超越他了);但滑动窗口是有长度限制的,怎么考虑呢?我们可以保存每个元素的序号,当发现队首元素的序号与当前考虑元素相比,已经出了滑动窗口,就弹出队首元素。
因为每个元素都只会进入队列一次且只会离开队列一次,可以认为时间复杂度是O(n)的。
下面请见std 外加详解:
- #include <cstdio>
- #include <iostream>
- #include <deque>
- using namespace std;
- struct num { //定义结构体存储元素的序号(id)及值(value)
- int id, value;
- num(int i, int v) : id(i), value(v) {} //构造关于结构体的函数,这样在后面的操作时比较简单
- };
- int n, k, a[], first = ;
- deque<num> dq;
- int main() {
- cin >> n >> k;
- for(int i = ; i <= n; ++i) {
- scanf("%d", &a[i]);
- if (dq.empty()) dq.push_back(num(i, a[i]));
- //若队列为空,则直接进入队列
- else {
- num f = dq.front(); //取队首元素(包括了id和value)
- if (i > f.id + k - ) dq.pop_front();
- //若队首元素的序号距当前元素太远(超出窗口长度)则弹出队首元素,相当于模拟一个窗口右滑的操作
- num b = dq.back(); //取队尾元素
- while (b.value < a[i]) { //若队尾元素小于当前元素则弹出队尾
- dq.pop_back();
- if (dq.empty()) break; //注意!队列为空则不能继续弹出,注意细小的边界
- b = dq.back();
- }
- dq.push_back(num(i, a[i])); //将当前元素放入队列中合适位置
- //如果不进行第10行的操作,则需要这样写:num qaq; qaq.id=i; qaq.value=a[i]; 此语句等价于第十行
- }
- if (i >= k) { //当考虑的元素个数达到窗口长度时,开始输出
- if (first) first = ;
- else printf("\n");//这种操作很鬼畜,会很好的将每次的答案进行换行且第一行被很好地跳过换行
- num f = dq.front();//取队首元素
- printf("第%d个滑动窗口的最大值为%d", i-k+, f.value);
- } //事实上,对于长度为n的序列,长度为k的窗口,共有n-k+1个不同的窗口
- }
- return ;
- }
滑动窗口
关于滑动窗口这个题,稍微有点饶脑,但请记住上文中的红色+下滑线那句话即可理解...
关于双端队列 deque 模板 && 滑动窗口 (自出)的更多相关文章
- 【C++】STL常用容器总结之五:双端队列deque
6.双端队列deque 所谓的deque是”double ended queue”的缩写,双端队列不论在尾部或头部插入元素,都十分迅速.而在中间插入元素则会比较费时,因为必须移动中间其他的元素.双端队 ...
- 双端队列-deque【集vector与list于一身的牺牲内存换功能完善】
看到双端队列(deque)了,书上是这样说的:除了栈和队列外还有一种限定性数据结构是双端队列:双端队列是限定插入和删除操作在表的两端进行的线性表:尽管双端队列看起来似乎比栈和队列更灵活,但实际上在应用 ...
- STL双端队列 deque
头文件:#include<deque> 构造方法: ①.创建一个没有任何元素的双端队列:deque<type> deq ②.用另一个类型相同双端队列初始化该双端队列:deque ...
- SPOJ - ADALIST,双端队列入门模板!
ADALIST - Ada and List 这道题时限6.5s,激动人心啊,好多人STL一顿乱写AC,哈哈,如果熟悉双端队列的话这道题其实是很水的. 题意:n个数的数列,然后接下来Q次操作,每次可以 ...
- C++ STL 双端队列deque详解
一.解释 Deque(双端队列)是一种具有队列和栈的性质的数据结构.双端队列的元素可以从两端弹出,其限定插入和删除操作在表的两端进行. 二.常用操作: 1.头文件 #include <deque ...
- Python 实现双端队列 Deque
操作 Deque() 创建一个空的双端队列 add_front(item) 从队头加入一个item元素 add_rear(item) 从队尾加入一个item元素 remove_front() 从队头删 ...
- STL队列 之FIFO队列(queue)、优先队列(priority_queue)、双端队列(deque)
1.FIFO队列 std::queue就是普通意思上的FIFO队列在STL中的模版. 1.1主要的方法有: (1)T front():访问队列的对头元素,并不删除对头元素 (2)T back(): ...
- 06 基本数据结构 - 双端队列(Deque)
一.双端队列(Deque) - 概念:deque(也称为双端队列)是与队列类似的项的有序集合.它有两个端部,首部和尾部,并且项在集合中保持不变. - 特性:deque 特殊之处在于添加和删除项是非限制 ...
- HDU-6375-度度熊学队列-双端队列deque/list
度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣. 初始时有 NN 个空的双端队列(编号为 11 到 NN ),你要支持度度熊的 QQ 次操作. ①11 uu ww valval 在编号为 u ...
随机推荐
- xxx was built without full bitcode" 编译错误解决
xxx was built without full bitcode" 编译错误解决 iOS 打包上线 All object files and libraries for bitcode ...
- 【leetcode刷题笔记】Search in Rotated Sorted Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
- CH6B12 最优高铁环
6B12 最优高铁环 0x6B「图论」练习 背景 幻影国建成了当今世界上最先进的高铁,该国高铁分为以下几类: S---高速光子动力列车---时速1000km/h G---高速动车---时速500km/ ...
- test20190611 NOIP模拟赛
题一:答题比赛 [问题描述] YYH报名参加了一个特殊的电视问答节目.这个节目共有n个问题,每回答正确1题,YYH就会获得1分,而每当YYH连续答对k题,那么他的现有得分乘以2,注意答对第k题后,是先 ...
- BZOJ2733:[HNOI2012]永无乡
浅谈线段树合并:https://www.cnblogs.com/AKMer/p/10251001.html 题目传送门:https://lydsy.com/JudgeOnline/problem.ph ...
- IP 地址漂移
1.概念 应用访问虚拟ip,当主服务器正常工作时,虚拟ip指向主服务器,当主服务器宕掉后,虚拟ip自动指向从服务器,当主服务器被人修好后,再自动指向主服务器, 这种虚拟ip的指向方式称为ip地址漂移. ...
- 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge
目录(?)[-] xml控件代码重用include xml控件代码重用merge 横屏和竖屏landsacpe portrait xml控件代码重用:include 如果我们定义一个控件,需要在不同的 ...
- 怎么查看mysql的安装目录,环境:windows+mysql+navicat
怎么查看mysql的安装目录 如果忘记了MySQL的安装目录,怎么快速找到呢?方法或许很多,作者觉得这种最方便了 环境:windows+mysql+navicat 方法:进入mysql命令行输入:sh ...
- 关于jquery登录的一些简单验证。
获取值之后的判断 $(function () { $("#btlogin").click(function () { var txtaccount = $("#txtac ...
- shell入门-连接符(并且、和、或者)
特殊符号:&& 说明:并且,左右两边是两条命令,左面的执行成功才会去执行右面的命令.右. 特殊符号:|| 说明:或者,左右两边是两条命令,左边的命令执行不成功,才会执行右面的命令 &a ...