这题滑动窗口,首先我那道题,发现是个区间最大值和最小值。很显然,可以用线段树和树状数组或者ST表去强行区间查询。

很不幸,牛客把内存卡的死死的,因为这题我在POJ 2823上做过,那里内存不严格,所以我线段树一发就过了。

这里线段树只能拿70f分。

滑动窗口是个经典的单调队列的题目,本题要求最大值和最小值,是维护2个单调队列,一个单调递减队列,队列头是保证对大值,一个是单调递增队列,保证队头最小值。

那么,我们如何去维护他呢??

这里我们以单调递减队列为例。

首先我们要知道,每次算区间的时候,整个区间k相当于移动了一格。那么我们没必要重新去计算。 我们每次去计算的时候,先判断下,队列顶的元素是不是超出我们的区间范围了,如果超出了,那么pop掉,因为超出区间范围,我们没必要算他了。如果当前元素大于队列顶部的那个元素,我们需要把队列顶部的那个元素弹出,因为后面最大值将不会是他了。判断好上面的情况后,我们需要把这个元素加到队列尾部,但是加的时候,我们需要去判断当前元素是不是大于尾部元素,如果大于尾部元素,也pop掉。我们实时维护的是队头最大值,这点要牢记。 这是最大值的做法,最小值也雷同,只要改变大于符号为小于符号即可。

题解大佬用了数组来模拟,我是用双端队列deque来模拟的。

#include <bits/stdc++.h>

using namespace std;

const int N=1e6+100;

int n,k;

struct Node
{
    int val;
    int pos;
}a[N];

deque<Node>dq;//计算最大值
deque<Node>dq2;//计算最小值 
int x[N];
int y[N];

void solve()
{
    for(int i=1;i<=n;i++)
    {
        if(dq.empty())
        {//如果是空的,直接加入 
            dq.push_back(a[i]); 
        }
        else
        {
            Node top=dq.front();//访问头结点
            if(i-top.pos>=k)
            {
                dq.pop_front();
            }//如果超出区间直接删掉
            if(a[i].val>dq.front().val)
            {
                dq.pop_front();
            } 
            while(!dq.empty()&&a[i].val>dq.back().val)
            {
                dq.pop_back();
            }
            dq.push_back(a[i]); 
        } 
        x[i]=dq.front().val;
    }

    for(int i=1;i<=n;i++)
    {
        if(dq2.empty())
        {//如果是空的,直接加入 
            dq2.push_back(a[i]); 
        }
        else
        {
            Node top=dq2.front();//访问头结点
            if(i-top.pos>=k)
            {
                dq2.pop_front();
            }//如果超出区间直接删掉
            if(a[i].val<dq2.front().val)
            {
                dq2.pop_front();
            } 
            while(!dq2.empty()&&a[i].val<dq2.back().val)
            {
                dq2.pop_back();
            }
            dq2.push_back(a[i]); 
        } 
        y[i]=dq2.front().val;
    }
}

int main()
{
    scanf("%d%d",&n,&k);

    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].val);
        a[i].pos=i;
    }

    solve();

    for(int i=k;i<=n;i++)
    {
        printf("%d%c",y[i],i==n?'\n':' '); 
    }

    for(int i=k;i<=n;i++)
    {
        printf("%d%c",x[i],i==n?'\n':' '); 
    } 
    return 0;
}