双端队列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 }
单调队列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 }
单调队列优化DP:
在用单调队列优化DP的时候,每次除维护序列的单调性外,还需要把队首已经没有用的元素pop_front()掉
能够用单调队列优化的DP一般都长成这个样子:
f[i] = max/min{f[k]} + ...
1 ≤ k < i
而优化的其实是求最值的过程:将O(n)优化到了O(1).
来源:oschina
链接:https://my.oschina.net/u/4417367/blog/3965300