• log 1886 滑动窗口(单调队列模版)


    coding使我忘记化学

    传送门


    如题,实质上是在考察单调队列,最大值和最小值可分别用一个单调队列排序输出。

    操作方便,定义两个数组分别储存队列和每个元素的序号

    由题得队列原则:队列数组中末尾元素的序号与开头元素序号之差不能大于k,使队列的范围保持为窗口的宽度

    在保证这点之后,只要同时保证队列始终是单调排序,这样当元素序号>=窗口宽度(保证窗口圈满元素)时,只要循环输出开头元素就可以了。

    那么如何保证队列单调?拿最大值举例:在向队列中添加元素的过程中,如果一个队列中元素X后的元素Y数值更大,那么X将失去成为最大值的可能性,故需被移出队列。

    以上即为本题队列操作方法,最小值同理。


    完整代码如下:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn=1000001;
    int item[maxn],line[maxn],element[maxn];//item存放序号,line为单调数列 
    int main()
    {
        int n,k,first,last;
        cin>>n>>k;
        
        for(int i=1;i<=n;i++)
        cin>>element[i];//读入 
        
        first=1;
        last=0;
        for(int i=1;i<=n;++i)//排序输出最小值 
            {
                while(first<=last&&line[last]>=element[i])
                last--;
                line[++last]=element[i];
                item[last]=i;
                while(item[first]<=i-k)
                first++;
                if(i>=k) cout<<line[first]<<" ";
            }
            
            cout<<"
    "; 
            first=1;
            last=0;//两个单调队列间过渡的细节不能忘记 
            
         for(int i=1;i<=n;++i)//排序输出最大值 
            {
                while(first<=last&&line[last]<=element[i])
                last--;
                line[++last]=element[i];
                item[last]=i;
                while(item[first]<=i-k)
                first++;
                if(i>=k) cout<<line[first]<<" ";
            }
            return 0;
          
    }
  • 相关阅读:
    HDOJ 1202 The calculation of GPA
    HDOJ 1197 Specialized Four-Digit Numbers
    HDOJ 1196 Lowest Bit(二进制相关的简单题)
    HDOJ 1194 Beat the Spread!(简单题)
    NOIP2018游记
    CF1043
    洛谷P1280 尼克的任务
    洛谷P1155 双栈排序
    SPOJ6340 ZUMA
    chessboard
  • 原文地址:https://www.cnblogs.com/charlesss/p/10116700.html
Copyright © 2020-2023  润新知