单调队列

概念

单调队列,即单调递增或单调递减的队列,其中元素从队尾入队,从队首或队尾出队。

应用

单调队列一般用于求区间内的最值问题。

列题

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

先看代码

#include <bits/stdc++.h>
using namespace std;
int n, m;
int q1[1000001], q2[1000001];
int a[1000001];
int min_deque()
{
    int h = 1, t = 0;
    for (int i = 1; i <= n; i++)
    {
        while (h <= t && q1[h] + m <= i)
            h++;
        while (h <= t && a[i] < a[q1[t]])
            t--;
        q1[++t] = i;
        if (i >= m)
            printf("%d ", a[q1[h]]);
    }
    cout << endl;
}
int max_deque()
{
    int h = 1, t = 0;
    for (int i = 1; i <= n; i++)
    {
        while (h <= t && q2[h] + m <= i)
            h++;
        while (h <= t && a[i] > a[q2[t]])
            t--;
        q2[++t] = i;
        if (i >= m)
            printf("%d ", a[q2[h]]);
    }
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    min_deque();
    max_deque();
    return 0;
}

说明:这道题,求的是一个区间内的最大值和最小值。对于数组中的某一个元素,我们只要关心它自己和它前k-1个数即可。

那么如何用队列处理呢?先简单说一下解题思路,以求最小值为例:一开始数组下标i为0,我们向队列里不停的放元素,并且一直保持队首位元素为最小值,直到第k个数,此时队首元素即为前k个数的最小值。然后我们把队首输出。继续往下走,走的过程中把队列中下标超出(i-k+1)~i区间范围的数踢掉,继续保持队首元素为区间内最小值,然后输出队首元素。

简单归纳一下,对于每一次循环,我们要做的就是:先踢掉超出区间范围的元素,放入元素并保证队首为数组中当前区间的最小值,输出队首,往复。队列内储存的就是放入元素之前区间内单调递增的最小值序列。

posted @ 2022-04-15 18:03  黎_lyh  阅读(92)  评论(0)    收藏  举报