POJ - 2823 Sliding Window (滑动窗口 单调队列模板题)

Sliding Window

 题目链接:https://vjudge.net/problem/POJ-2823

An array of size n ≤ 10 6 is given to you. There is a sliding window of size kwhich 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的一部分;
建立两个双端队列,该队列是有序队列,队头的元素分别为最小和最大;

进队列:如果当前元素比队尾元素大,或者队列为空,则直接进队;  如果当前元素比队尾元素小,则队尾元素出队,直至当前元素大于队尾元素或队列为空,然后当前元素入队;

 如果当前元素比队尾元素小,或者队列为空,则直接进队;     如果当前元素比队尾元素大,则队尾元素出队,直至当前元素小于队尾元素或队列为空,然后当前元素入队;                                                                                                                                  就是维护队列的单调性

出队列:取每个窗口对应的最小值的时候,要保证队头元素在窗口里面;
队头出列时,判断队头元素是否在窗口里面,如果在则直接输出;否则,则一直出队头元素,直至所出的队头元素在窗口里面,然后输出。 就是如果队头元素与当前入队的元素之间的距离大于等于k时 就不属于这个窗口的元素,就出队

一个单调队列,末端插入,弹出,首端只弹出,不插入。队首始终为最值。
如果新入队的元素与队头元素的距离>=滑动窗口的宽度,则队头元素出队列。

 

代码:

#include
#include
#include
using namespace std;
const int N=1000005;
int a[N],ma[N],mi[N];
struct node
{
    int val,pos;
}maxq[N],minq[N];
int main()
{
    int n,k,maxh=0,maxt=0,minh=0,mint=0;
    scanf("%d%d",&n,&k);
    for(int i=0;i=a[i]) mint--;
        minq[mint].val=a[i],minq[mint].pos=i;
        ++mint;
        while(maxh=k) minh++;
        while(maxh=k) maxh++;

        while(minh=a[i]) mint--;
        minq[mint].val=a[i],minq[mint].pos=i;
        ++mint;
        while(maxh

 

代码2:(下标入队)

#include
#include
#include
using namespace std;
const int N=1000005;
int a[N],qi[N],qa[N],mi[N],ma[N];
int main()
{
    int n,m,la=0,ra=0,li=0,ri=0;
    scanf("%d%d",&n,&m);
    for(int i=0;i=a[i]) --ri;
        qi[ri++]=i;
        while(la=m) li++;
        while(la=m) la++;
        while(li=a[i]) --ri;
        qi[ri++]=i;
        while(la

 

你可能感兴趣的:(单调栈,单调队列)