单调队列

单调队列是一种操作受限的数据结构

只允许从队首出队、队首和队尾入队。

它可以用于维护区间内的最大值和最小值。

性质:

1.单调队列内的所有元素的相对位置和原列表中相同。

2.队首的元素根据需要,一定是最大(或最小的)。

3.队首的元素一定是最先入队的,队尾的元素是走后入队的。

4.队列中的元素保持着单调性。

 

看一道模版题:

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

代码如下,注释解释了各个操作的意义。

 1 #include <queue>
 2 #include <vector>
 3 #include <iostream>
 4 using namespace std;
 5 struct node{
 6     int id;
 7     int data;
 8 };
 9 deque<node> max_dq;
10 deque<node> min_dq;
11 vector<int> max_ans;
12 vector<int> min_ans;
13 int main(){
14     int n,k,temp;
15     cin >> n >> k;
16     for(int i = 1; i <= n; i++){
17         cin >> temp;
18         while(not max_dq.empty() and max_dq.back().data < temp){
19             max_dq.pop_back();
20         }
21         
22         while(not min_dq.empty() and min_dq.back().data > temp){
23             min_dq.pop_back();
24         }
25         /*
26          * 以最大值为例进行说明 :
27          * 单调队列维护区间最大值
28          * 队首元素最大
29          * 当新加入一个元素时,进行两个判断 :
30          *
31          * 1. while(队尾的元素比新元素的data小: pop_front()) , 这是因为 , 由于后入队的元
32          *    素必定比先入队的元素晚进入我们的滑动窗口,同时呢, 这个元素又比当前队尾的元素的值大
33          *    那么, 当前队尾的元素有生之年(luogu某题解里的奇妙词汇,感觉用的好恰当哈哈哈)不可
34          *    能成为最大值了,直接出队。
35          *
36          * 2. while(队首的元素与新元素的id相差超过了maxsize :pop_back())
37          *    这是因为, 由于区间的大小是有限的, 当两个元素的 id 相差超过了区
38          *    间长度时,队首元素需要出队然后将新元素 push_back()
39          *
40          * 当第 k 个元素入队后,开始打印元素
41          */
42         while(not max_dq.empty() and i - max_dq.front().id >= k){
43             max_dq.pop_front();
44         }
45         
46         while(not min_dq.empty() and i - min_dq.front().id >= k){
47             min_dq.pop_front();
48         }
49         
50         node New;
51         New.id = i; New.data = temp;
52         max_dq.push_back(New);
53         min_dq.push_back(New);
54         if(i >= k){
55             max_ans.push_back(max_dq.front().data);
56             min_ans.push_back(min_dq.front().data);
57         }
58     }
59     int first = 1;
60     for(auto it = min_ans.begin(); it not_eq min_ans.end(); it++){
61         if(first)first = 0;else cout<<" ";
62         cout<<*it;
63     }
64     first = 1;cout<<endl;
65     for(auto it = max_ans.begin(); it not_eq max_ans.end(); it++){
66         if(first)first = 0;else cout<<" ";
67         cout<<*it;
68     }
69     return 0;
70 }
posted @ 2020-01-15 19:29  popozyl  阅读(205)  评论(0编辑  收藏  举报