单调栈与队列的应用

1、单调栈一般是求数列某个数最左侧第一个大于或小于这个数的数

题目如下:

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int stk[N], top;

int n;

int main()
{
    cin >> n;
    
    while (n -- )
    {
        int x;
        scanf("%d", &x);
        while(top && stk[top] >= x) top --; //栈不空且大于这个数的话,则弹出
        if(top) printf("%d ", stk[top]); //栈不空的话,栈顶则是小于它的第一个数。
        else printf("-1 ");
        stk[++ top] = x; //压栈
    }
}

2、单调队列的典型应用,滑动窗口

题目如下:

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e6+10;

int a[N], q[N];
int hh, tt = -1;

int main()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
    
    for (int i = 0; i < n; i ++ )
    {
        if(hh <= tt && q[hh] < i- k + 1) hh ++; 
        /*如果队头(队列存的是数组下标,q[hh]
        代表队头是数组的第几个数字)已经出了窗口,则用hh++的方式让队头始终在窗口里*/
        while(hh <= tt && a[q[tt]] >= a[i]) tt --;
        /*如果队列不空,而且队尾元素大于当前新进队列元素,则移除队尾元素,使队列单调 */
        
        q[++ tt] = i;
        if(i >= k - 1)printf("%d ",a[q[hh]]);
    }
    
    puts("");
    
    tt = -1, hh = 0; // 勿忘记清空队列
     for (int i = 0; i < n; i ++ )
    {
        if(hh <= tt && q[hh] < i- k + 1) hh ++; 
        /*如果队头(队列存的是数组下标,q[hh]
        代表队头是数组的第几个数字)已经出了窗口,则用hh++的方式让队头始终在窗口里*/
        while(hh <= tt && a[q[tt]] <= a[i]) tt --;
        /*同理*/
        
        q[++ tt] = i;
        if(i >= k - 1)printf("%d ",a[q[hh]]);
    }
    
}

3、总结

牢记单调栈与队列的应用。

posted @ 2022-01-14 21:12  Medjay  阅读(33)  评论(0编辑  收藏  举报