poj2823(单调队列)

Sliding Window

题意:

  给出一个数组,有一个滑窗每次可以包括k个数(从最左端开始),每次向右移动一步,求每次滑窗中k个数中的最大值和最小值。

分析:

  用一个单调递增队列求最小值,一个单调递减队列求最大值,但是因为滑窗的大小为k,所以每次要对队列中最左端的位置进行判断。

代码:

#include <stack>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))

const int maxn=1e6+100;

int n,k;

int a[maxn];
int que[maxn],minval[maxn],maxval[maxn];

void getMin()
{
    int head=0,rear=0;
    for(int i=1;i<=n;i++){
        while(rear>head&&a[que[rear-1]]>=a[i])   rear--;
        que[rear++]=i;
        if(i<k) continue;
        while(que[head]<i-k+1)  head++;
        minval[i]=a[que[head]];
    }
}

void getMax()
{
    int head=0,rear=0;
    for(int i=1;i<=n;i++){
        while(rear>head&&a[que[rear-1]]<=a[i])   rear--;
        que[rear++]=i;
        if(i<k) continue;
        while(que[head]<i-k+1)  head++;
        maxval[i]=a[que[head]];
    }
}

void print()
{
    for(int i=k;i<=n;i++){
        if(i>k) printf(" ");
        printf("%d",minval[i]);
    }
    printf("
");
    for(int i=k;i<=n;i++){
        if(i>k) printf(" ");
        printf("%d",maxval[i]);
    }
    printf("
");
}

int main()
{
//    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }

        getMin();
        getMax();
        print();
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shutdown113/p/9381975.html