单调队列
单调队列是一种操作受限的数据结构
只允许从队首出队、队首和队尾入队。
它可以用于维护区间内的最大值和最小值。
性质:
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 }
---- suffer now and live the rest of your life as a champion ----