1. 程式人生 > >Sliding Window 單調佇列解決--經典滑動視窗問題--求視窗的最大值最小值

Sliding Window 單調佇列解決--經典滑動視窗問題--求視窗的最大值最小值

這就要用到單調遞減或單調遞增佇列來實現,它的頭元素一直是佇列中的最小值或最大值。我們可以從佇列的末尾插入一個元素,可以從佇列的兩端刪除元素。

插入元素:

對於單調遞減佇列:隊頭放最大值,為了保持佇列的遞減性,我們在插入元素v的時候,要將隊尾元素與v比較,如果隊尾<v,則刪除隊尾元素,然後繼續將新的隊尾元素與v比較,直到隊尾元素>v,這時才將v插入隊尾。

刪除隊首元素:

隊尾元素的刪除剛剛已經說了,那麼隊首的元素什麼時候刪除呢?當隊首元素的索引或下標小於i-k+1的時候,說明隊首元素已經沒用了,因為他已經不在窗裡了,所以當隊首元素索引或下標<i-k+1時,將隊首元素刪除。

#include<iostream>
#include<cstdio>
#include<deque>
using namespace std;
const int maxn=1e6+6;
struct node
{
    int val,id;
};
int minn[maxn],maxx[maxn],a[maxn];
int main()
{
    int n,k,i;
    node now;
    deque<node>qmin;
    deque<node>qmax;
    scanf("%d%d",&n,&k);
    scanf("%d",&now.val);
    now.id=1;
    a[1]=now.val;
    minn[1]=now.val;
    qmin.push_back(now);
    for(i=2;i<=n;i++)
    {
        scanf("%d",&a[i]);
        now.val=a[i];
        now.id=i;
        while(!qmin.empty()&&qmin.back().val>a[i])
            qmin.pop_back();
        qmin.push_back(now);
        if(!qmin.empty()&&qmin.front().id<i-k+1)
            qmin.pop_front();
        minn[i]=qmin.front().val;
    }
    maxx[1]=a[1];
    now.val=a[1];
    now.id=1;
    qmax.push_back(now);
    for(i=2;i<=n;i++)
    {
        now.val=a[i];
        now.id=i;
        while(!qmax.empty()&&qmax.back().val<a[i])
            qmax.pop_back();
        qmax.push_back(now);
        if(!qmax.empty()&&qmax.front().id<i-k+1)
            qmax.pop_front();
        maxx[i]=qmax.front().val;
    }
    for(i=k;i<n;i++)
        printf("%d ",minn[i]);
    printf("%d\n",minn[n]);
    for(i=k;i<n;i++)
        printf("%d ",maxx[i]);
    printf("%d\n",maxx[n]);
}