滑动窗口/单调队列

https://www.acwing.com/problem/content/156/

以找最小的为例子:

q[N] : 存放单调递增的序列下标 ,模拟单调队列, hh为较小的队头,每次输出,则输出 a[ q[ hh] ]

 当所要维护的窗口的起点超过hh,即单调队列的头元素时,hh++ ,让头更新;因为q数组存放的一定是单调递增的, 所以每次输出 q[ hh ]一定是窗口中最小的。 

 ?关于为什么要 i - k + 1 >= q[ hh ]

q 放的下标对应的数一定是单调递增的,当窗口后移时,hh可能已经滑出窗口了,由于每轮只添加一个元素,所以用 if 。这样q数组就起到一个预先处理的效果。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, k;
int a[N] ,q[N];//q序列用于存放一个单调递增的队列, i控制它的范围

int main()
{
    cin >> n >> k;
    for(int i = 0; i < n; i ++) cin >> a[i];
    int hh = 0, tt = -1;
//找最小
    //起点i - k + 1   终点i
    for( int i = 0; i < n; i ++){
        if(hh <= tt && i - k + 1 > q[hh]) hh ++;//队头滑出窗口,更新队头
        while( hh <= tt && a[q[tt]] >= a[i]) tt --;//队尾元素不要比当前的大,否则弹出
        q[ ++tt ] = i;//当前元素下标进入队列
        if(i >= k - 1) printf("%d ", a[q[hh]]);//维护到k个区间时 可以开始输出
    }
    puts("");
//找最大
    hh = 0, tt = -1;
    //起点i - k + 1   终点i
    for( int i = 0; i < n; i ++){
        if(hh <= tt && i - k + 1 > q[hh]) hh ++;//队头滑出窗口,更新队头
        while( hh <= tt && a[q[tt]] <= a[i]) tt --;//队尾元素不要比当前的大,否则弹出
        q[ ++tt ] = i;//当前元素下标进入队列
        if(i >= k - 1) printf("%d ", a[q[hh]]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值