滑动窗口的单调队列

今天的训练赛HDU 4122,卡到最后也没出来,结束后和队友冷静分析代码后才发现错在一个简单的错误上,修改后A了

赛后看题解,大家的题解中大都提到了要用单调队列。

去网上搜单调队列。。文章无外乎就两种。。= =  抄袭好严重呀

1.http://zhonghuan.info/2014/09/16/%E6%B5%85%E6%9E%90%E5%8D%95%E8%B0%83%E9%98%9F%E5%88%97/

简单的单调队列

2.http://blog.pureisle.net/archives/477.html

结合了滑动窗口的单调队列

 

而HDU4122这个题明显是用到了第二种

 

差不多该回寝室了。。。明天上午回来搞~

 

简单的来说,单调队列的作用:不断地向缓存数组里读入元素,也不时地去掉最老的元素,不定期的询问当前缓存数组里的最小的元素。

 

单调队列与队列唯一的不同就在于它不仅要保存元素的值,而且要保存元素的索引(当然在实际应用中我们可以只需要保存索引,而通过索引间接找到当前索引的值)。

为了让读者更明白一点,我举个简单的例子。 
假设数列为:8,7,12,5,16,9,17,2,4,6.N=10,k=3. 
要求元素的生存时间不超过k(可以正好为k) 
那么我们构造一个长度为3的单调递减队列: 
首先,那8和它的索引0放入队列中,我们用(8,0)表示,每一步插入元素时队列中的元素如下: 
0:插入8,队列为:(8,0) 
1:插入7,队列为:(8,0),(7,1) 
2:插入12,队列为:(12,2) 
3:插入5,队列为:(12,2),(5,3) 
4:插入16,队列为:(16,4) 
5:插入9,队列为:(16,4),(9,5) 
。。。。依此类推 
那么f(i)就是第i步时队列当中的首元素:8,8,12,12,16,16,。。。

为了方便操作,运用pair类型

#include <iostream>
using namespace std;
typedef pair<int,int> Pair;
Pair f[100];
int a[100];
int main () {
    int n,k;
    cin>>n>>k;
    for (int i=0;i<n;i++)
        cin>>a[i];
    int tail=0,head=0;
    Pair t(a[0],0);
    int i=0;
    f[i]=t;
    while (i<n-1){
        i++;//新元素入队
        Pair t(a[i],i);
        int j;
        for (j=tail;j>=head;j--){//维护队尾
            if (t.first<f[j].first) break;
        }
        f[j+1]=t;tail=j+1;
        
        while (i-f[head].second>k){//注意这里,有的题意是不超过k,有的题意是不多于k。
            head++;
        }
        cout<<"&"<<a[i]<<" ";
        cout<<f[head].first<<endl;
    }
    return 0;
}
View Code

 

posted @ 2015-08-07 21:49  ACBingo  阅读(295)  评论(0编辑  收藏  举报