STL-Deque(双端队列)与单调队列的实现

前言:

  STl是个好东西,虽然他在不开O2的条件下会跑的很慢,但他着实会让你的代码可读性大大提高,令你的代码看起来既简单又整洁。

双端队列:

  顾名思义,双端队列是有两个头的,一个队首指针,一个队尾指针,先进先出或是先进后出都可以实现。

基本操作:

  (1) deque<int> dq 定义一个int类型的双端队列dq

  (2) deque<int> dq(15) 队列dq具有15个元素单位

  (3) deque<int> dq(15,10) 队列dq内15个元素初始值均为10

  (4) dq.push_back(x) 将x放入dq的末端

  (5) dq.push_front(z) 将x放入dq的前端

  (6) dq.size() 返回队列中元素的个数

  (7) dq.pop_front() 弹出队列的前端元素
  (8) dq.pop_back() 弹出队列的后端元素

  (7) dq.front() 返回队列的前端元素
  (8) dq.back() 返回队列的后端元素

代码实现:

 1 #include<cstdio>
 2 #include<queue>
 3 using namespace std;
 4 const int maxn=1e5+5;
 5 deque<int> dq;
 6 int a[maxn]={0,1,2,3,4,5,6,7,8,9,10};
 7 int main(){
 8     dq.push_front(a[1]),dq.push_front(a[2]),dq.push_front(a[3]);
 9     dq.push_back(a[4]),dq.push_back(a[5]),dq.push_back(a[6]);
10     dq.push_front(a[7]),dq.push_front(a[8]);
11     dq.push_back(a[9]),dq.push_back(a[10]);
12     dq.pop_front(),dq.pop_front();
13     dq.pop_back(),dq.pop_back();
14     int n=dq.size();//n=6
15     for(int i=1;i<=n;i++){
16         printf("%d ",dq.front());
17         dq.pop_front();
18     }
19     return 0;
20 }
deque

小结:

  双端队列不仅可以用来优化搜索,更能用来写单调队列这个神奇的xx来优化其他的一些东西(例如DP)

单调队列:

  顾名思义,单调队列是单调递增或者是单调递减的一种队列,就像一个递增队列,若将数列1 6 5 3 8放入队列中,则队列的每一步变化为:1、1 6、1 5、1 3、1 3 8 。每当放入的元素使得队列不在单调,则弹出队尾的元素,直到使得队列元素单调。

代码实现:

 1 #include<cstdio>
 2 #include<queue>
 3 using namespace std;
 4 const int maxn=1e5+5;
 5 deque<int> q_up;
 6 deque<int> q_dw;
 7 int a[maxn]={0,1,6,5,3,8};
 8 int main(){
 9     for(int i=1;i<=5;i++){
10         while(q_up.size()&&q_up.back()>=a[i]) 
11             q_up.pop_back();
12         q_up.push_back(a[i]);
13     }
14     int n=q_up.size();
15     for(int i=1;i<=n;i++){
16         printf("%d ",q_up.front());
17         q_up.pop_front();
18     }
19     return 0;
20 }
q_up

   当然,单调队列也可以用来维护滑动窗口的区间最大值和区间最小值。

例题_滑动窗口(洛谷P1886)

题目描述

  现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

 1 #include<cstdio>
 2 #include<queue>
 3 using namespace std;
 4 const int maxn=1e6+5;
 5 struct cp{
 6     int ord,x;
 7 };
 8 deque<cp> q1,q2;
 9 int n,k;
10 int a[maxn],s1[maxn],s2[maxn];
11 inline void q_max(cp e){
12     while(q1.size()){
13         cp q=q1.back();
14         if(q.x>=e.x) q1.pop_back();
15         else break;
16     }
17     while(q1.size()){
18         cp q=q1.front();
19         if(q.ord==e.ord-k) q1.pop_front();
20         else break;
21     }
22     q1.push_back(e);
23     cp q=q1.front();
24     if(e.ord-k>=0) s1[e.ord-k+1]=q.x;
25 }
26 inline void q_min(cp e){
27     while(q2.size()){
28         cp q=q2.back();
29         if(q.x<=e.x) q2.pop_back();
30         else break;
31     }
32     while(q2.size()){
33         cp q=q2.front();
34         if(q.ord==e.ord-k) q2.pop_front();
35         else break;
36     }
37     q2.push_back(e);
38     cp q=q2.front();
39     if(e.ord-k>=0) s2[e.ord-k+1]=q.x;
40 }
41 inline int read(){
42     char ch=getchar();
43     int x=0,f=1;
44     while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
45     while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
46     return x*f;
47 }
48 int main(){
49     n=read(),k=read();
50     for(int i=1;i<=n;i++) a[i]=read();
51     for(int i=1;i<=n;i++){
52         cp q;
53         q.ord=i,q.x=a[i];
54         q_max(q),q_min(q);
55         printf("%d ",s1[i])
56     }
57     for(int i=1;i<=n-k+1;i++) ;
58     putchar('\n');
59     for(int i=1;i<=n-k+1;i++) printf("%d ",s2[i]);
60     return 0;
61 }
Code

  结构体类型的队列不知为何不能用 q.front().ord,所以代码显得特别冗长,如果有dalao可以解决这个问题,蒟蒻洗耳恭听!

(以上问题现已解决,附上代码)

 1 #include<cstdio>
 2 #include<queue>
 3 using namespace std;
 4 const int maxn=1e6+5;
 5 struct cp{
 6     int ord,x;
 7 };
 8 deque<cp> q1,q2;
 9 int n,k;
10 int a[maxn],s1[maxn],s2[maxn];
11 inline void q_max(cp e){
12     while(q1.size()&&q1.back().x>=e.x) q1.pop_back();
13     if(q1.size()&&q1.front().ord==e.ord-k) q1.pop_front();
14     q1.push_back(e);
15     if(e.ord-k>=0) s1[e.ord-k+1]=q1.front().x;
16 }
17 inline void q_min(cp e){
18     while(q2.size()&&q2.back().x<=e.x) q2.pop_back();
19     if(q2.size()&&q2.front().ord==e.ord-k) q2.pop_front();
20     q2.push_back(e);
21     if(e.ord-k>=0) s2[e.ord-k+1]=q2.front().x;
22 }
23 inline int read(){
24     char ch=getchar();
25     int x=0,f=1;
26     while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
27     while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
28     return x*f;
29 }
30 int main(){
31     n=read(),k=read();
32     for(int i=1;i<=n;i++) a[i]=read();
33     for(int i=1;i<=n;i++){
34         cp q=(cp){i,a[i]};
35         q_max(q),q_min(q);
36     }
37     for(int i=1;i<=n-k+1;i++) printf("%d ",s1[i]);
38     putchar('\n');
39     for(int i=1;i<=n-k+1;i++) printf("%d ",s2[i]);
40     return 0;
41 }
Code(如果您喜欢压行)

  如有任何问题,蒟蒻洗耳恭听!

posted @ 2018-08-05 16:11  Rising_Date  阅读(1590)  评论(0编辑  收藏  举报