zoukankan      html  css  js  c++  java
  • 【洛谷P1886】滑动窗口

    滑动窗口

    【题目描述】

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

     

    思路:

    k<=N<=1000000,暴力是拿不到全分的,要想解决这个问题,理想的时间复杂度应是O(n),我们可以用一个单调队列维护。

    单调队列原理:

      以维护最大值为例:

      对于每个新加入区间的值,显而易见的是:对于向右移动的“窗口”,即当前长度为n的区间中,若存在data[q[i]]比data[q[j]]大且q[i]>q[j](q[i]表示队列中的第i个元素的编号,data[i]表示编号为i的元素的值),则可以保证q[j]在以后的区间取最大值时是不会产生影响的,我们便可以将q[j]删除,从而得到更加优秀的时间复杂度,所以,当一个新的值入队时,便可以将在其前面入队且值比它小的元素删除。 我们便可以发现可以用一个单调队列维护。 当然,对于不在当前区间内的“老”元素,要把它从队列中删除。

    贴代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,k,a[1000010],queue[1000010],tail,head=1,i;
    int main()
    {
        scanf("%d%d",&n,&k);
        for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
      //最小值 单调递减的队列
    for(i=1;i<=k;i++)    //前k个数入队 { while(a[i]<=a[queue[tail]]&&tail>=head) tail--; queue[++tail]=i; } for(i=k;i<=n;i++)    //k+1~n依次入队 { while(a[i]<=a[queue[tail]]&&tail>=head) tail--; queue[++tail]=i; if(queue[head]<i-k+1) head++; printf("%d ",a[queue[head]]); } puts("");
      //最大值 单调递增的队列 memset(queue,
    0,sizeof(queue)); for(i=1;i<=k;i++) { while(a[i]>=a[queue[tail]]&&tail>=head) tail--; queue[++tail]=i; } for(i=k;i<=n;i++) { while(a[i]>=a[queue[tail]]&&tail>=head) tail--; queue[++tail]=i; if(queue[head]<i-k+1) head++; printf("%d ",a[queue[head]]); } return 0; }
  • 相关阅读:
    css+ul+li方式 横向再纵向排列
    b表中有的塞给a表
    .net remoting的两种实现方式 cow
    Prism之Module cow
    2012项目总结 cow
    WCF学习笔记 cow
    也谈委托,事件和回调 cow
    理清apply(),call()的区别和关系 cow
    CLR via C#学习之线程栈,托管堆,值类型和引用类型 cow
    细说系列笔记 cow
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/8490640.html
Copyright © 2011-2022 走看看