Sliding Window 单调队列解决--经典滑动窗口问题--求窗口的最大值最小值

http://poj.org/problem?id=2823

这就要用到单调递减或单调递增队列来实现,它的头元素一直是队列中的最小值或最大值。我们可以从队列的末尾插入一个元素,可以从队列的两端删除元素。

插入元素:

对于单调递减队列:队头放最大值,为了保持队列的递减性,我们在插入元素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]);
}

猜你喜欢

转载自blog.csdn.net/qq_37891604/article/details/81296346