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
#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] ]=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