单调队列

数据结构

单调队列使用的是一种在一端可以出队,另一端可以出队和入队的队列,其中只能出队的作为队头,既能出队又能入队的称为队尾。如下图:

 用途

求区间最大(最小)值

实现

最大值

区间内的数保证单调递减,此时队头为此区间的最大值。

队头:队头出队用来维护区间大小。

队尾:队尾出队入队用来维护区间单调性。

为什么要使队列内的数单调递减?因为队列内存储的数都是有可能成为区间最大值的数。或者说队列中存储的数是(最大值,第二大,第三大。。。),所以要单调递减。

最小值

区间内的数保证单调递增,此时队头为此区间的最小值。

队头:队头出队用来维护区间大小。

队尾:队尾出队入队用来维护区间单调性。

为什么要使队列内的数单调递增?因为队列内存储的数都是有可能成为区间最小值的数。或者说队列中存储的数是(最小值,第二小,第三小。。。),所以要单调递增。

 

P1886 滑动窗口 /【模板】单调队列

 

#include<cstdio>
#include<iostream>
#include<vector>
#include<iomanip>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iterator>
using namespace std;

struct Node {
    int id;
    int val;
};
int n, k;
int num[1000005];
Node q[1000005];    //队列

void getmax() {
    int f = 1;
    int r = 0;

    for (int i = 1; i <= n; i++) {
        while (f <= r && q[f].id + k <= i)f++;    //队头出队,保证队列内的数是当前区间的数
        while (f <= r && q[r].val < num[i])r--;    //队尾出队,保证单调递减
        r++;
        q[r].id = i;
        q[r].val = num[i];
        if (i >= k)cout << q[f].val<<" ";
    }
}

void getmin() {
    int f = 1;
    int r = 0;

    for (int i = 1; i <= n; i++) {
        while (f <= r && q[f].id + k <= i)f++;    //队头出队,保证队列内的数是当前区间的数
        while (f <= r && q[r].val > num[i])r--;    //队尾出队,保证单调递增
        r++;
        q[r].id = i;
        q[r].val = num[i];
        if (i >= k)cout << q[f].val << " ";
    }
}


int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> num[i];
    }
    getmin();
    cout << endl;
    getmax();
    
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值