<题目链接>

<转载于>>> >

题目大意:

给你一段序列和一个长为k的窗口,这个窗口从最左边逐渐向右滑,直到滑到最右边,问你,该窗口在滑动的过程中,最大值和最小值是多少。

解题分析:

解决这个问题可以使用一种叫做单调队列的数据结构,它维护这样一种队列:

a)从队头到队尾,元素在我们所关注的指标下是递减的(严格递减,而不是非递增),比如查询如果每次问的是窗口内的最小值,那么队列中元素从左至右就应该递增,如果每次问的是窗口内的最大值,则应该递减,依此类推。这是为了保证每次查询只需要取队头元素。

b)从队头到队尾,元素对应的时刻(此题中是该元素在数列a中的下标)是递增的,但不要求连续,这是为了保证最左面的元素总是最先过期,且每当有新元素来临的时候一定是插入队尾。

满足以上两点的队列就是单调队列,首先,只有第一个元素的序列一定是单调队列。

那么怎么维护这个单调队列呢?无非是处理插入和查询两个操作。

对于插入,由于性质b,因此来的新元素插入到队列的最后就能维持b)继续成立。但是为了维护a)的成立,即元素在我们关注的指标下递减,从队尾插入新元素的时候可能要删除队尾的一些元素,具体说来就是,找到第一个大于(在所关注指标下)新元素的元素,删除其后所有元素,并将新元素插于其后。因为所有被删除的元素都比新元素要小,而且比新元素要旧,因此在以后的任何查询中都不可能成为答案,所以可以放心删除。

对于查询,由于性质b,因此所有该时刻过期的元素一定都集中在队头,因此利用查询的时机删除队头所有过期的元素,在不含过期元素后,队头得元素就是查询的答案(性质a),将其返回即可。

由于每个元素都进队出队一次,因此摊销复杂度为O(n)。

单调队列模板题,维护两个单调队列,一个维护最小值,单调递增,最小值在队首,另一个维护最大值,单调递减,最大值在队首,然后在窗口滑动的过程中,记录下队首即可 。

#include <cstdio>
#include <cstring>

;
int n,k;
int a[M],qmax[M],qmin[M],pmax[M],pmin[M],mx[M],mi[M];

void get_max(){
    ,head=;
    ;i<k;i++){
        while(head<=tail&&qmax[tail]<=a[i])
            --tail;
        qmax[++tail]=a[i];
        pmax[tail]=i;
    }
    for(int i=k;i<=n;i++){
        while(head<=tail&&qmax[tail]<=a[i])
            --tail;
        qmax[++tail]=a[i];
        pmax[tail]=i;
        )
            ++head;
        mx[i-k+]=qmax[head];
    }
    ;i<=n-k+;i++){
        i==?printf("%d",mx[i]):printf(" %d",mx[i]);
    }
    printf("\n");
}

void get_min(){
    ,head=;
    ;i<k;i++){  //先开始将前k-1个元素插入优先队列
        while(head<=tail&&qmin[tail]>=a[i]) //求最小值,维护一个单调递增的队列,最小值在队首
            --tail;
        qmin[++tail]=a[i];  //将队尾不符合条件的元素删除后,将该元素插入队尾
        pmin[tail]=i;  //队尾元素的位置
    }
    for(int i=k;i<=n;i++){ //然后将从第k个元素及以后插入优先队列,此时就要注意过期的队首元素的删除
        while(head<=tail&&qmin[tail]>=a[i])   //依然是插入时的维护
            --tail;
        qmin[++tail]=a[i];
        pmin[tail]=i;
        )   //如果队首元素的下标过小,则将该过期的队首元素删除
            ++head;
        mi[i-k+]=qmin[head];   //记录下新队首元素的下标
    }
    ;i<=n-k+;i++){
        i==?printf("%d",mi[i]):printf(" %d",mi[i]);
    }
    printf("\n");
}

int main(){
    while(scanf("%d %d",&n,&k)!=EOF){
        ;i<=n;i++){
            scanf("%d",&a[i]);
        }
        get_min();
        get_max();
    }
    ;
}

2018-09-23

POJ 2823 Sliding Window​ (模板题)【单调队列】的更多相关文章

  1. POJ 2823 Sliding Window 再探单调队列

    重新刷这个经典题,感觉跟以前不一样了,变得更加容易理解了,不讲解了,看代码.注意:要用C++提交,用G++会超时.. 代码: #include <iostream> #include &l ...

  2. POJ 2823 Sliding Window + 单调队列

    一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1)   从队首删除 (2)   从队尾删除 (3)   从队尾插入 (4)   ...

  3. POJ 2823 Sliding Window 题解

    POJ 2823 Sliding  Window 题解 Description An array of size n ≤ 106 is given to you. There is a sliding ...

  4. 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

    To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...

  5. POJ 2823 Sliding Window(单调队列入门题)

      Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 67218   Accepted: 190 ...

  6. poj 2823 Sliding Window (单调队列入门)

    /***************************************************************** 题目: Sliding Window(poj 2823) 链接: ...

  7. 题解报告:poj 2823 Sliding Window(单调队列)

    Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is m ...

  8. POJ 2823 Sliding Window 【单调队列】

    题目链接:http://poj.org/problem?id=2823 题目大意:给出一组数,一个固定大小的窗体在这个数组上滑动,要求出每次滑动该窗体内的最大值和最小值. 这就是典型的单调队列,单调队 ...

  9. 【单调队列】poj 2823 Sliding Window

    http://poj.org/problem?id=2823 [题意] 给定一个长度为n的序列,求长度为k的滑窗内的最大值和最小值 [思路] 裸的单调队列 注意用C++提交,不然会T,orz我用G++ ...

随机推荐

  1. Confluence 6 配置服务器基础地址

    服务器基础地址(Server Base URL)是用户访问 Confluence 的 URL 地址.这个基础的 URL 地址必须与你在浏览器中访问 Confluence 中的地址. Confluenc ...

  2. 关于ios进入后台界面后 播放声音解决方案

    1 最近我在做环信视频通话时,遇到了一个新功能就是APP在后台的时候能对方能视频或者音频过来的时候 能够播放声音 根据查询相关资料得到如下解决办法 NSError *error; AVAudioSes ...

  3. JS去除空格和换行的正则表达式(推荐)

    //去除空格  String.prototype.Trim = function() {  return this.replace(/\s+/g, "");  }    //去除换 ...

  4. 关于使用easyui为前端框架,加载表格数据较多时在火狐浏览器会出现表格片段不停闪烁问题的兼容问题解决。

    1.项目是可视化管理系统,加载的数据较多,使用谷歌浏览器从登陆界面跳转到主页时还算干净利落,但是使用火狐浏览器时在这一过程中在数据没有加载完毕之前,整个页面就仿佛是在闪烁,可以看到闪烁的是表格字段的片 ...

  5. Jmeter测试demo

    复制代码,保存为.jmx文件 需要安装插件: JMeterPlugins-ExtrasLibs E:\软件\apache-jmeter-3.0\lib\ext <?xml version=&qu ...

  6. 如何用TortoiseSVN对文件进行操作

    我们如何用TortoiseSVN修改文件,添加文件,删除文件,以及如何解决冲突等. 添加文件 在检出的工作副本中添加一个Readme.txt文本文件,这时候这个文本文件会显示为没有版本控制的状态,如图 ...

  7. java中的相对目录问题

    在java开发过程中,常常需要使用本地文件内容文件.在调试他人代码的过程中,可能不经意间改变了源代码的根目录(顶级目录),从而导致“java io filenotfoundexception ”.解决 ...

  8. 17/11/24 05:08:44 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

    2017-11-24 21:20:25 1:什么叫失望,什么叫绝望.总之是一脸懵逼的继续...... 之前部署的hadoop都是hadoop-2.4.1.tar.gz,这几天换成了hadoop-2.6 ...

  9. oracle创建用户和密码以及授权登录问题

    创建有户名和密码CREATE USER 用户名 IDENTIFIED BY 密码;分配权限GRANT connect,dba to 用户名; 1:使用oracle的命令行登录oracle的方式(安装好 ...

  10. spring+redis的集成,redis做缓存

    1.前言 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.我们都知道,在日常的应用中,数据库瓶颈是最容易出现的 ...