Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 36326 | Accepted: 10762 | |
Case Time Limit: 5000MS |
Description
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3 1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
题目:http://poj.org/problem?id=2823
之前在讨论 hdu魔板 这道题的时候,有人提到了O(1)队列,于是 度娘搜索到了这道题。做一下咯~
①什么是O(1)队列?
O(1)队列又称单调队列,顾名思义,就是队列中的元素是单调的。
要么单调递增,要么单调递减。
那么,构建单调队列有什么用呢?
我们维护一个队列后,我们查找当前队列内元素最大值/最小值 就可以是O(1)的速度了。
或许有人(比如我刚开始就想过)问:用优先队列,设置一下优先级不就可以了。
但是,要知道STL的东东,都挺耗时间的,尤其是 优先队列。
一般用单调队列做的题,对时间要求比较高,所以优先队列显然不能满足要求。
②单调队列如何维护
以单调递增队列来举例:
1、如果队列的长度一定,先判断队首元素是否在规定范围内,如果超范围则增长队首。
2、每次加入元素时和队尾比较,如果当前元素小于队尾且队列非空,则减小尾指针,队尾元素依次出队,直到满足队列的调性为止
要特别注意头指针和尾指针的应用。
参考资料:http://www.cnblogs.com/neverforget/archive/2011/10/13/ll.html
http://xuyemin520.is-programmer.com/posts/25964
And 这道题就可以解决了。
/************************************** *************************************** * Author:Tree * *From :http://blog.csdn.net/lttree * * Title : Sliding Window * *Source: poj 2823 * * Hint : 单调队列 * *************************************** **************************************/ #include <stdio.h> #define MAX 1000001 int n,k; int pre1,pre2,lst1,lst2,len_max,len_min; // 两个队列的头指针与尾指针,最大值的下标,最小值的下表 int num[MAX],Increase[MAX],Decrease[MAX],Max[MAX],Min[MAX]; // Num存数据,递增与递减队列,最大值,最小值的数组。 // 递增序列的压入操作 void in_max(int i) { while( pre1<=lst1 && num[ Increase[lst1] ]<num[i] ) --lst1; Increase[++lst1]=i; // 如果大于等于k个数,就需要向最大值数组赋值 if( i>=k ) { if(Increase[pre1]<=i-k) pre1++; Max[len_max++]=num[ Increase[pre1] ]; } } // 递减序列的压入操作 void in_min(int i) { while( pre2<=lst2 && num[ Decrease[lst2] ]>num[i] ) --lst2; Decrease[++lst2]=i; // 如果大于等于k个数,就需要向最小值数组赋值 if( i>=k ) { if(Decrease[pre2]<=i-k) pre2++; Min[len_min++]=num[ Decrease[pre2] ]; } } int main() { int i; while( ~scanf("%d%d",&n,&k) ) { // 初始化 pre1=pre2=len_max=len_min=0; lst1=lst2=-1; // 读入数据 for(i=1;i<=n;++i) { scanf("%d",&num[i]); in_max(i); in_min(i); } // 输出数据 for( i=0;i<len_min-1;++i ) printf("%d ",Min[i]); printf("%d\n",Min[len_min-1]); for( i=0;i<len_max-1;++i ) printf("%d ",Max[i]); printf("%d\n",Max[len_max-1]); } return 0; }