单调队列——POJ - 2823

题目含义

给出一个区间的长度,要你在一堆数中移动这个区间(保持区间长度不变),找出对应的最大最小值 

题目解析

这个区间在向右移动,那么时时刻刻有数离开这个区间,有数加入这个区间,这样的话可以考虑单调队列

把这些数按从大到小的顺序放入一个数组,并且从大到小判断这个数是否满足在这个区间,不满足就取出

这样队列头就是这个区间的最大值,同理最小

题目代码

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e6+7;
int n,k,h,t;
int a[maxn],q[maxn],maxx[maxn],minn[maxn];
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    h=1,t=0;
    for(int i=1;i<=n;i++){
        while(h<=t&&a[q[t]]<=a[i])t--;///满足单调数组单调递减的性质
        q[++t]=i;
        while(i-k>=q[h])h++;///判断此时的最大值a[q[h]]的下标在不在区间内
        maxx[i]=a[q[h]];
    }
    h=1,t=0;
    for(int i=1;i<=n;i++){
        while(h<=t&&a[q[t]]>=a[i])t--;///单调递增的数组
        q[++t]=i;
        while(i-k>=q[h])h++;
        minn[i]=a[q[h]];
    }
    if(k>=n){
        printf("%d\n%d\n",minn[n],maxx[n]);
    }
    else{
        for(int Qi=k;i<n;i++)
            printf("%d ",minn[i]);
        printf("%d\n",minn[n]);
        for(int i=k;i<n;i++)
            printf("%d ",maxx[i]);
        printf("%d\n",maxx[n]);
    }
    return 0;
}

 挺简单的,本来以为能一次过的,结果又忘了算完最大值后要重置h和t

posted @ 2019-07-21 18:53  helman78  阅读(76)  评论(0编辑  收藏  举报