前言:
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 }
小結:
雙端隊列不僅可以用來優化搜索,更能用來寫單調隊列這個神奇的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 }
當然,單調隊列也可以用來維護滑動窗口的區間最大值和區間最小值。
例題_滑動窗口(洛谷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 }
結構體類型的隊列不知為何不能用 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 }
如有任何問題,蒟蒻洗耳恭聽!