【模板】deque实现单调队列

浪尽此生 提交于 2020-05-06 10:54:21

双端队列deque容器:

关于deque最常用的有这几个函数

都是成员函数

双端队列模板题:【洛谷】P2952 [USACO09OPEN]牛线Cow Line

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<deque>
 6 using namespace std;
 7 
 8 int n, cnt;
 9 deque<int> q;
10 
11 int main() {
12     scanf("%d\n", &n);
13     char s[21];
14     for(int i=1; i<=n; ++i) {
15         gets(s);
16         if(s[0] == 'A')
17             if(s[2] == 'L') q.push_front(++cnt);
18             else q.push_back(++cnt);
19         if(s[0] == 'D') {
20             int m = 0, j = 1;
21             while(s[j]<'0' || s[j]>'9') ++j;
22             while(s[j]>='0' && s[j]<='9')
23                 m = (m << 3) + (m << 1) + s[j] - 48, ++j;
24             while(m--) {
25                 if(s[2] == 'L') q.pop_front();
26                 else q.pop_back();
27             }
28         }
29 
30     }
31     deque<int>::iterator it;
32     for(it=q.begin(); it!=q.end(); ++it)
33         printf("%d\n", *it);
34 }
P2952 [USACO09OPEN]牛线Cow Line

 

单调队列deque容器实现:

设一个数组a,可以修改某一个元素的值,求a中所有元素的最小(大)值

每次从头扫到尾的时间复杂度O(n2)太高了,st表虽然是O(1)查询但不支持修改

可以使用线段树O(n log2 n)来做但复杂度还是不够优秀,常数还大

单调队列登场了:

每次加入双端队列尾一个元素num时,从队尾将队列中所有比num大的元素都pop出去,再push_back(num)

这样就能实现单调队列了。

单调队列模板题:【洛谷】P1440 求m区间内的最小值

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<deque>
 5 using namespace std;
 6 
 7 const int MAXN = 2000000 + 1;
 8 
 9 int n, m;
10 int a[MAXN];
11 deque<int> q;
12 
13 inline int read() {
14     int x=0, f=1; char ch=getchar();
15     while(ch<'0' || ch>'9') {
16         if(ch == '-') f = -1;
17         ch = getchar();
18     }
19     while(ch>='0' && ch<='9')
20         x=(x<<3)+(x<<1)+ch-48, ch=getchar();
21     return x * f;
22 }
23 
24 int main() {
25     n = read(), m = read();
26     for(int i=1; i<=n; ++i) a[i] = read();
27     puts("0");
28     for(int i=1; i<n; ++i) {
29         if(i>m && q.front()==a[i-m]) q.pop_front();
30         while(!q.empty() && q.back()>a[i]) q.pop_back();
31         q.push_back(a[i]);
32         printf("%d\n", q.front());
33     }
34 }
P1440 求m区间内的最小值

 

单调队列优化DP:

在用单调队列优化DP的时候,每次除维护序列的单调性外,还需要把队首已经没有用的元素pop_front()

能够用单调队列优化的DP一般都长成这个样子:

  f[i] = max/min{f[k]} + ...

  1 ≤ k < i

而优化的其实是求最值的过程:O(n)优化到了O(1).

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!