原题链接:
http://poj.org/problem?id=2823
An array of size n ≤ 10 6 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example:
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.
Output
There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
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
题意:
有n个数字组成的序列,有一个长度为k个窗口,从第一个一直滑动到最后一个,美妙滑动一次,每次滑动向后一个,每滑动一次就输出窗口里的数列的最小值和最大值。具体格式见样例。
题解:
这道题目可以利用单调队列,利用数组记录当前窗口的最大(小)值。
以找最小值举例说明:
滑动窗口时,插入元素:删除掉所有的所有比插入元素大的数值,代码里其实就是将队列q的右端点向左移,直到有比 插入元素小的时候插入。
如何实现窗口移动,并且保持队列单调呢?
如果队首元素的位置小于窗口的左界,则删除,其他的不用管,因为最终输出的时队首元素,在队首其后的元素对其不产生影响,并且如果在之后的移动中,之前未删除的不在窗口的元素也会被删除的。
(更多细节见代码,请读者细细体会)
注意:这道题目耗时比较长,用cin,cout输入输出会超时
附上AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN=1e6+5;
int a[MAXN],q[MAXN],n,k;
void workmin()
{
int l=1,r=0,i=0;
for(; i<k-1; i++)//初始化队前k-1个元素
{
while(l<=r&&a[q[r]]>a[i]) r--;//当左端点小于右端点并且删除掉比插入元素大的队尾元素
q[++r]=i;//插入输入元素
}
for(; i<n; i++)//窗口移动
{
if(q[l]<=i-k) l++;//删除不在窗口的队首元素
while(l<=r&&a[q[r]]>a[i]) r--;//含义同上,实现窗口移动
q[++r]=i;
printf("%d ",a[q[l]]);//输出最小值
}
printf("\n");
}
void workmax()
{
int l=1,r=0,i=0;
for(; i<k-1; i++)//初始化队的前k-1个元素
{
while(l<=r&&a[q[r]]<a[i]) r--;//左端点小于右端点,并且删除队尾比插入元素小的元素实现单调递减
q[++r]=i;//插入元素
}
for(; i<n; i++)
{
if(q[l]<=i-k) l++;//不在窗口内的都删除
while(l<=r&&a[q[r]]<a[i]) r--;
q[++r]=i;
printf("%d ",a[q[l]]);//输出最大值printf
}
printf("\n");
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=0; i<n; i++)
scanf("%d",a+i);
workmin();
workmax();
}
return 0;
}
欢迎评论!