C++单调队列与单调栈 滑动窗口题解

题目描述:

现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:

The array is [1 3 -1 -3 5 3 6 7], and k = 3.

C++单调队列与单调栈 滑动窗口题解_第1张图片

输入:

第1行:2个整数N,K(K<=N<=1000000) 第2行:N个整数,表示数组的N个元素(<=2*10^9)

输出:

第1行:滑动窗口从左向右移动每个位置的最小值,每个数之间用一个空格分开 第2行:滑动窗口从左向右移动每个位置的最大值,每个数之间用一个空格分开

输入样例:

8 3
1 3 -1 -3 5 3 6 7

输出样例:

-1 -3 -3 -3 3 3
3 3 5 5 6 7

解题思路:

首先,我们眼里只有一个词————暴搜,没错这就是我们的思路,但是此暴搜非彼暴搜,我们是要有技术含量的(不然你怎么AC这道题呢)。

废话少说,现在我们可以想象,我们可以用两个单调队列来保存一个不下降序列,一个不上升序列。而判断这个单调队列中的最大和最小值是否还在窗口中,只需要我们在单调队列中储存其的序号,再用一个while循环将前头指针增加,就可以将其踢出队列。

代码实现:

#include
#include
#include
using namespace std;
int m,n,a[1000005],a1[1000005],tail1=1,tail2=1,back1,back2,s1[1000005],s2[1000005];
struct node{
    int x;
}s[1000005];
int read()//读入优化
{
    int x=0,f=1;
    char s=getchar();
    while(s<'0'||s>'9')
    {
        if(s=='-')
            f=-1;
        s=getchar();
    }
    while(s>='0'&&s<='9')
    {
        x*=10;
        x+=s-'0';
        s=getchar();
    }
    return x*f;
}
int main()
{
    n=read();
    m=read();
    for(int i=1;i<=n;i++)
    {
        s[i].x=read();
        if(i<=m)//判断数是否在第一个窗口中。
        {
            while(tail1<=back1&&back1>=0)
            {
                if(s[i].x>=s[a[back1]].x)//若现在读入的数大于等于队尾的数,就将其踢出。
                    back1--;
                else
                    break;
            }
            back1++;
            a[back1]=i;
            while(tail2<=back2&&back2>=0)
            {
                if(s[i].x<=s[a1[back2]].x)//若现在读入的数小于等于队尾的数,就将其踢出。
                    back2--;
                else
                    break;
            }
            back2++;
            a1[back2]=i;
        }
    }
    s1[1]=s[a[tail1]].x;
    s2[1]=s[a1[tail2]].x;
    for(int i=m+1;i<=n;i++)
    {
        while(tail1<=back1&&back1>=0)
        {
            if(s[i].x>=s[a[back1]].x)
                back1--;
            else
                break;
        }
        back1++;
        a[back1]=i;
        while(tail2<=back2&&back2>=0)
        {
            if(s[i].x<=s[a1[back2]].x)
                back2--;
            else
                break;
        }
        back2++;
        a1[back2]=i;
        while(a[tail1]

 

你可能感兴趣的:(算法,单调队列)