滑动窗口的单调队列
今天的训练赛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; }