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(如果您喜歡壓行)

  如有任何問題,蒟蒻洗耳恭聽!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM