[洛谷 1886] 滑动窗口

倾然丶 夕夏残阳落幕 提交于 2019-11-27 12:30:45

---恢复内容开始---

一道经典的单调队列题目


单调指的是元素的规律呈现为一种单调性,递增,递减,或者自定义

队列指的是只能从队首和队尾进行操作(所以单调队列也可以用STL的deque实现),但单调队列只需要队首的弹出、队尾的插入和弹出

题目的要求是每连续k个数中的最大值和最小值,以维护最大值为例,对于任意在范围内,且在

---恢复内容结束---

### 一道经典的单调队列题目

单调指的是元素的规律呈现为一种单调性,递增,递减,或者自定义1576249-20190816123042323-327652433.png

队列指的是只能从队首和队尾进行操作(所以单调队列也可以用STL的deque实现),但单调队列只需要队首的弹出、队尾的插入和弹出

题目的要求是每连续k个数中的最大值和最小值,以维护最大值为例,对于任意在范围内,且在队列中的数x,y,新进队一个数z,z > x && z > y,那么z从队尾进队,x,y出队

Code:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>

using namespace std;
const int maxn = 1000100;

int n, k;
int q[maxn], a[maxn];

void getmin()
{
    int head = 0, tail = 0;
    for (int i = 1; i < k; i++)
    {
        while (head <= tail && a[q[tail]] >= a[i])
            tail--;
        q[++tail] = i;
    }
    for (int i = k; i <= n; i++)
    {
        while (head <= tail && a[q[tail]] >= a[i])
            tail--;
        q[++tail] = i;
        while (q[head] <= i - k)
            head++;
        printf("%d ", a[q[head]]);
    }
}

void getmax()
{
    int head = 0, tail = 0;
    for (int i = 1; i < k; i++)
    {
        while (head <= tail && a[q[tail]] <= a[i])
            tail--;
        q[++tail] = i;
    }
    for (int i = k; i <= n; i++)
    {
        while (head <= tail && a[q[tail]] <= a[i])
            tail--;
        q[++tail] = i;
        while (q[head] <= i - k)
            head++;
        printf("%d ", a[q[head]]);
    }
}

int main()
{
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    getmin();
    printf("\n");
    getmax();
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!