POJ

来源:互联网 发布:java import include 编辑:程序博客网 时间:2024/05/17 00:57
Description

An array of size n ≤ 106 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.
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

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的窗口(也就是说通过这个窗口可以看到k个数),开始将窗口放在数组最左端,然后每次往右移动一个位置,问每次窗口中数的最小值和最大值.

分析:看到Sliding Window就想到了计算机网络里面TCP协议的滑动窗口,但这两者并没有啥联系.按照正常思维的话,我们肯定是一段一段的找最值,不用说肯定会TLE,但是我们可以在每次比较的时候记录前面的结果,这时我们阔以用一个单调递减队列(队首元素最大)来记录最大值,用单调递增(队首元素最小)队列来记录最小值,在每次更新队列的时候要注意判断一下队首元素的下标是否包括在滑动窗口内.

//另外还要多说一句,很多单调队列的题目都是滑窗问题的变形.

参考代码:

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<queue>#include<iostream>using namespace std;const int maxn = 1e6+10;int n,k;int arr[maxn];int a[maxn];int b[maxn];int qmin[maxn];int qmax[maxn];int main(){while( ~scanf("%d%d",&n,&k)){for( int i = 0; i < n; i++)scanf("%d",&arr[i]);//求最小值,单调递增队列,队头元素最小int p = 0;int head = 0;int tail = 0;for( int i = 0; i < k-1 && i < n; i++){while( head < tail && arr[i] <= arr[qmin[tail-1]])tail--;qmin[tail++] = i;}for( int i = k-1; i < n; i++){while( head < tail && arr[i] <= arr[qmin[tail-1]])tail--;while( head < tail && qmin[head] < i-k+1)head++;qmin[tail++] = i;a[p++] = arr[qmin[head]];}for( int i = 0; i < p-1; i++)printf("%d ",a[i]);if( p > 1)printf("%d\n",a[p-1]);//求最大值,单调递减队列,队首元素最大int q = 0;head = 0;tail = 0;for( int i = 0; i < k-1 && i < n; i++){while( head < tail && arr[i] >= arr[qmax[tail-1]])tail--;qmax[tail++] = i;}for( int i = k-1; i < n; i++){while( head < tail && arr[i] >= arr[qmax[tail-1]])tail--;while( head < tail && qmax[head] < i-k+1)head++;qmax[tail++] = i;b[q++] = arr[qmax[head]];}for( int i = 0; i < q-1; i++)printf("%d ",b[i]);if( q > 1)printf("%d\n",b[q-1]);}return 0;}