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<<"\n"; 
        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;
      
}

 

posted @ 2018-12-13 21:58  .Terena  阅读(186)  评论(0编辑  收藏  举报