洛谷 P1886 滑动窗口(单调队列)

原题
本题是一道很经典的单调队列模板题,如果想要O(1)的时间内回答每个窗口,用ST表也可以,但是这道题洛谷上会被卡MLE,所以就来介绍一下单调队列。
因为是初次尝试,也为了便于理解,所以用数组模拟了单调队列
AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,a[1000005],p[1000005];
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
      scanf("%d",&a[i]);
    }
    int head=1,tail=0;//定义单调队列的头指针和尾指针,储存的是数组下标。
    for(int i=1;i<=n;i++)//我们先求最小值,头指针储存最小值下标
    {
      if(head<=tail&&p[head]<i-k+1)//首先我们要先判断队列内的元素在不在滑动窗口内,如果不在,则头指针++
        head++;
      while(head<=tail&&a[p[tail]]>a[i])//如果比队尾元素小的话,就继续往下寻找(tail++),直到找不到
        tail--;
     p[++tail]=i;//加入队尾
     if(i>=k)//保证滑动窗口合法
        printf("%d ",a[p[head]]);
    }
    puts("");
    head=1,tail=0;
     for(int i=1;i<=n;i++)
    {
      while(head<=tail&&p[head]<i-k+1)
        head++;
      while(head<=tail&&a[p[tail]]<a[i])//找最大值同理,只要改变下进入队列的比较符号即可
        tail--;
     p[++tail]=i;
     if(i>=k)
        printf("%d ",a[p[head]]);
    }
return 0;
}

posted @ 2020-03-18 00:30  Pecoz  阅读(104)  评论(0编辑  收藏  举报