单调队列的实现

匿名 (未验证) 提交于 2019-12-03 00:40:02

单调队列的作用,归纳成一句话就是不断读入元素,不时去掉元素,随时查询最值

应用的话就比较高级了,除了滑动窗口这个题目,还有动态规划的效率优化,当然还有别的以后再整理

单调队列由于要不断从两端进行队列操作,所以采用双端队列来实现

在此例中,所有的数据都是放在a数组中的,我们用一个p来表示a数组中某一个元素的下标,然后在单调队列中存下标即可

我们以维护单调递增队列举例

while(!q.empty()&&a[p]<=a[q.back()])  //维护单调队列              q.pop_back();         q.push_back(p);

对于一个新的p,我们用a[p]和当前单调队列的最后一个位置的元素作比较,如果发现比新插入元素的大的,全部扔出去,因为我这个队列只维护单调增,只方便找最小值即可,大的没用

然而,对于一些过期的元素,虽然他们很小,我们还是要把它们扔掉才可以

while(!q.empty()&&q.front()<p-k+1)  //维持题意的区间长度              q.pop_front();  //移出出界的元素 

接下来根据题意输出队列中元素的值即可

由于我们是单调递增队列,维护的是最小值,那么队首元素就是最有用的

if(p>=k-1)  //元素进够k个后开始输出答案              cout<<a[q.front()]<<" ";         p++; 

下面给出滑动窗口的完整实现

 1 //aininot260  2 //不断读入元素,不时去掉元素,随时询问最值  3 #include<iostream>  4 #include<queue>  5 using namespace std;  6 const int maxn=1000005;  7 int n,k;  8 int a[maxn];  9 deque<int> q; 10 int main() 11 { 12     cin>>n>>k; 13     for(int i=0;i<n;i++) 14         cin>>a[i]; 15     int p=0; 16     while(p<n) 17     { 18         while(!q.empty()&&a[p]<=a[q.back()])  //维护单调队列  19             q.pop_back(); 20         q.push_back(p); 21         while(!q.empty()&&q.front()<p-k+1)  //维持题意的区间长度  22             q.pop_front();  //移出出界的元素  23         if(p>=k-1)  //元素进够k个后开始输出答案  24             cout<<a[q.front()]<<" "; 25         p++;  26     } 27     cout<<endl; 28      29     p=0; 30     q.clear(); 31     while(p<n) 32     { 33         while(!q.empty()&&a[p]>=a[q.back()])  //维护单调队列  34             q.pop_back(); 35         q.push_back(p); 36         while(!q.empty()&&q.front()<p-k+1)  //维持题意的区间长度  37             q.pop_front();  //移出出界的元素  38         if(p>=k-1)  //元素进够k个后开始输出答案  39             cout<<a[q.front()]<<" "; 40         p++;  41     } 42     cout<<endl; 43     return 0; 44 } 

原文:https://www.cnblogs.com/aininot260/p/9304573.html

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