• 【OI】单调队列


    所谓单调队列,就是一个保持着某种性质的队列,通常是队列从队头到队尾,维护一种递增递减的关系。

    这种队列通常用来解决一些连续区间的最值问题。

    这种队列的入队要保证符合当前的性质,例如一个递增的单调序列(从左到右是从头到尾):7,9,10,11

    这时,入队时要保证是递增的:例如12这个元素可以入队,而10这个元素不行。

    这时我们看队头,这就是整个队列中最小的元素。所以,递增的队列可以维护最小值;递减的队列可以维护最大值。

    当然,实现一个单调队列需要看题目要求,通常需要对队头和队尾进行更新。

    例如这道题:

    P1886 滑动窗口

    题目描述

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

    这道题可以使用单调队列来做。

    在滑动窗口的时候,改变只有窗口序列中的第一个元素和最后一个元素,所以我们可以把一开始的序列同样的放到两个单调队列中,一个递增,一个递减,分别维护最小值和最大值。

    用求最小值(递增单调队列)做例子,我们对每个元素运行这样一个判断:

    1.如果当前元素<队尾,那么删除队尾。不停执行该操作,直到队为空且没有可以删除的队尾为止。

    2.在队尾加上当前元素。

    3.如果队头离开了窗口的范围,那么删除队头。

    求最大值的操作类似。

    根据上题,我们可以总结出单调队列一般有这样的步骤:

    1.如果当前元素小于或者大于(递增或者递减)队尾,那么删除队尾。不停执行该操作,直到队为空且没有可以删除的队尾为止。

    2.在队尾加上当前元素。

    3.如果队头离开了题目的范围,那么删除队头。

    P1440 求m区间内的最小值

    题目描述

    一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值。若前面的数不足m项则从第1个数开始,若前面没有数则输出0。

    这道题依然用单调队列做。注意,这道题的区间指的是每一项的前m个数,不包括这一项。

    所以,我们维护一个递增的单调队列,长度最长为m,步骤类似上文所讲。

    代码:

    #include<iostream>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<map>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll INF=99999999;
    const int MaxN = 2000010;
    int a[MaxN];
    int que[MaxN][2];
    int n,m,head = 1,tail;
    int main()
    {
        //freopen("testdata.in","r",stdin);
        //freopen("testdata.out","w",stdout);
        
        scanf("%d%d",&n,&m);
        
        
        
        
        for(int i = 1; i <= n; i++){
            scanf("%d",&a[i]);    
        } 
        printf("0
    ");
        que[++tail][0] = a[1];
        que[tail][1] = 1;
        for(int i = 2; i <= n; i++){
            
            
            
            while(head <= tail && a[i-1] < que[tail][0]){
                tail--;
            }
            que[++tail][0] = a[i-1];
            que[tail][1] = i-1;
        
            while(head <= tail &&que[head][1] < i-m)
                head++;
            
            
            printf("%d
    ",que[head][0]);
        }
        
        return 0;
    }
    P1440
  • 相关阅读:
    Java 8与Runtime.getRuntime().availableProcessors()
    nginx配置
    周末完成工作小结
    CentOS 8 安装MySQL 8.0
    centOS8网络获取不了
    IUAP平台新增菜单存储过程
    centOS8安装Docker
    Mybatis里用到的设计模式
    2020,回顾过往,展望未来
    使用 Apache SSI(Server Side Includes) 制作多语言版静态网页
  • 原文地址:https://www.cnblogs.com/dudujerry/p/10420701.html
Copyright © 2020-2023  润新知