<题目链接>

<转载于>>> >

题目大意:

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

解题分析:

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

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

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

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

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

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

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

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

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

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. ;
  5. int n,k;
  6. int a[M],qmax[M],qmin[M],pmax[M],pmin[M],mx[M],mi[M];
  7.  
  8. void get_max(){
  9. ,head=;
  10. ;i<k;i++){
  11. while(head<=tail&&qmax[tail]<=a[i])
  12. --tail;
  13. qmax[++tail]=a[i];
  14. pmax[tail]=i;
  15. }
  16. for(int i=k;i<=n;i++){
  17. while(head<=tail&&qmax[tail]<=a[i])
  18. --tail;
  19. qmax[++tail]=a[i];
  20. pmax[tail]=i;
  21. )
  22. ++head;
  23. mx[i-k+]=qmax[head];
  24. }
  25. ;i<=n-k+;i++){
  26. i==?printf("%d",mx[i]):printf(" %d",mx[i]);
  27. }
  28. printf("\n");
  29. }
  30.  
  31. void get_min(){
  32. ,head=;
  33. ;i<k;i++){ //先开始将前k-1个元素插入优先队列
  34. while(head<=tail&&qmin[tail]>=a[i]) //求最小值,维护一个单调递增的队列,最小值在队首
  35. --tail;
  36. qmin[++tail]=a[i]; //将队尾不符合条件的元素删除后,将该元素插入队尾
  37. pmin[tail]=i; //队尾元素的位置
  38. }
  39. for(int i=k;i<=n;i++){ //然后将从第k个元素及以后插入优先队列,此时就要注意过期的队首元素的删除
  40. while(head<=tail&&qmin[tail]>=a[i]) //依然是插入时的维护
  41. --tail;
  42. qmin[++tail]=a[i];
  43. pmin[tail]=i;
  44. ) //如果队首元素的下标过小,则将该过期的队首元素删除
  45. ++head;
  46. mi[i-k+]=qmin[head]; //记录下新队首元素的下标
  47. }
  48. ;i<=n-k+;i++){
  49. i==?printf("%d",mi[i]):printf(" %d",mi[i]);
  50. }
  51. printf("\n");
  52. }
  53.  
  54. int main(){
  55. while(scanf("%d %d",&n,&k)!=EOF){
  56. ;i<=n;i++){
  57. scanf("%d",&a[i]);
  58. }
  59. get_min();
  60. get_max();
  61. }
  62. ;
  63. }

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. ios 清除缓存文件

    获取缓存文件的大小 由于缓存文件存在沙箱中,我们可以通过NSFileManager API来实现对缓存文件大小的计算. 计算单个文件大小 +(float)fileSizeAtPath:(NSStrin ...

  2. Eclipse 软件 Java 解决:出现的editor does not contain a main type错误框 问题

    Eclipse 软件 解决:出现的 editor does not contain a main type 错误框 问题 当你运行 Java文件是,如果弹出了下面的 错误框: 出现错误的原因: 当前的 ...

  3. JS和Jquery获取和修改label的值的示例代码

    abel标签在JS和Jquery中使用不能像其他标签一样用value获取它的值,下面有个不错的示例,希望大家可以学习下 来源:  <  JS和Jquery获取和修改label的值的示例代码  & ...

  4. NIO(四)

    使用非直接缓冲区和直接缓冲区复制同一个文件,看一下时间差别 1.创建非直接缓冲区测试类 package com.cppdy.nio; import java.io.FileInputStream; i ...

  5. MySQL数据库驱动jar包

    地址:https://www.mysql.com/

  6. ES6笔记

    /** * Created by Administrator on 2017/4/13. */ /*---------------------Es6编码规范---------------------* ...

  7. Vue+restfulframework示例

    一.简单回顾vue 前不久我们已经了解了vue前端框架,所以现在强调几点: 修改源: npm config set registry https://registry.npm.taobao.org 创 ...

  8. cf161d 求距离为k的点对(点分治,树形dp)

    点分治裸题,但是用树形dp也能做 /* dp[u][k]表示在u下距离k的点数量 */ #include<bits/stdc++.h> using namespace std; ]; ], ...

  9. php url函数

    1.base64_encode 与 base64_decode base64_encode(string) 表示使用 MIME base64 对数据进行编码 base64_decode(string) ...

  10. jQuery 选择器demo练习

    <!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...