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

咕咕咕

单调队列板子题

 

一、基本

1.单调队列:

特殊的双端队列,内部元素。分为最大队列(单调递增)和最小队列(单调递减)两种

 

二、应用

本题中:大部分单调队列优化的动态规划问题都和定长连续子区间的最值问题

 

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int sum = 0,p = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
            p = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (sum *= 10) += ch - '0';
        ch = getchar();
    }
    return sum * p;
}

const int N = 1e6 + 5;
int n,k,head,tail;
int a[N],fn[N],fx[N],num[N],q[N];

void dpmin()
{
    head = 1,tail = 0;
    for(int i = 1;i <= n;i++)
    {
        while(num[head] < i - k + 1 && head <= tail)
            head++;
        while(a[i] <= q[tail] && head <= tail)
            tail--;
        num[++tail] = i;
        q[tail] = a[i];
        fn[i] = q[head];
    }
}

void dpmax()
{
    head = 1,tail = 0;
    for(int i = 1;i <= n;i++)
    {
        while(num[head] < i - k + 1 && head <= tail)
            head++;
        while(a[i] >= q[tail] && head <= tail)
            tail--;
        num[++tail] = i;
        q[tail] = a[i];
        fx[i] = q[head];
    }
}

int main()
{
    n = read(),k = read();
    for(int i = 1;i <= n;i++)
        a[i] = read();
    dpmin();
    dpmax();
    for(int i = k;i <= n;i++)
        printf("%d ",fn[i]);
    printf("\n");
    for(int i = k;i <= n;i++)
        printf("%d ",fx[i]);
    return 0;
}
裸题

 

posted @ 2019-08-15 08:29  darrrr  阅读(168)  评论(0编辑  收藏  举报