zoukankan      html  css  js  c++  java
  • 【模板】 滑动窗口

    传送门

    题意

    长度为(n)的序列,只能看到长度为(k)的滑动窗口,从数组的最左边移动到最右边,求滑动过程中每个滑动窗口的最大值和最小值

    数据范围

    (1leq nleq 10^{6})

    题解

    • 单调队列中存下标,判断窗口长度,当求窗口中的最小值时,如果队列中存在两个元素,满足 (a_{i} geq a_{j})(i<j),那么(a_{i})不会被选为最小值,出队;

    • 此时队列中剩下的元素严格单调递增,所以队头就是整个队列中的最小值,可以用(O(1))的时间找到;

    • 为了维护队列的这个性质,我们在往队尾插入元素之前,先将队尾大于等于当前数的元素全部弹出即可;

      • 这样所有数均只进队一次,出队一次,所以时间复杂度是(O(n))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<n;i++)
    const int N = 1e6+10;
    int a[N];
    int que[N];
    int main()
    {
        int n,k;
        cin>>n>>k;
        rep(i,1,n+1)
            scanf("%d",&a[i]);
        int hh=1,tt=0;
    
        rep(i,1,n+1)
        {
            if(hh <= tt && i - k + 1 > que[hh]) hh++;
            while(hh<=tt && a[que[tt]] >= a[i]) tt--;
            que[++tt] = i;
            if(i > k - 1)
                printf("%d " ,a[que[hh]]);
        }
        puts("");
        hh=1,tt=0;
    
        rep(i,1,n+1)
        {
            if(hh <= tt && i - k + 1 > que[hh]) hh++;
            while(hh <= tt && a[que[tt]] <= a[i]) tt--;
            que[++tt] = i;
            if(i-k+1>0)
                printf("%d " ,a[que[hh]]);
        }
        puts("");
    }
    
  • 相关阅读:
    第三次作业
    第二次作业
    第一次作业
    仪仗队(欧拉函数)
    自己随便做的,没做完就没耐心继续了。呵呵
    从别处见到一位大神的代码 飞扬的小鸟(flappy bird)
    简易迷宫游戏c++
    STL做法 平衡树
    基于百度地图api + AngularJS 的入门地图
    javascript 简易文本编辑器
  • 原文地址:https://www.cnblogs.com/hhyx/p/13711185.html
Copyright © 2011-2022 走看看