<题目链接>

<转载于>>> >

题目大意:

给你一段序列和一个长为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. swift 学习- 10 -- 类和结构体

    // '类和结构体' 是人们构建代码所使用的一种通用且灵活的构造体, 我们可以使用完全相同的语法规则来为 '类和结构体' 定义属性 (变量 和 常量) 和添加方法, 从而扩展 类和结构体 的功能 // ...

  2. 在启用属性的情况下启动 Confluence 6

    在一些情况下,你可以希望 Confluence 在系统启动的时候就对属性文件进行打印.如果你的 Confluence 经常进行重启,并且你可能忘记来启动针对系统诊断的属性文件日志开关. 编辑 CONF ...

  3. 对Swoole、Workerman和php自带的socket的理解

    为什么php自带的socket不怎么听说,基本都是用swoole,workerman去实现? 1.PHP的socket扩展是一套socket api,仅此而已. swoole,用C实现,它的socke ...

  4. Memcached简介及环境安装

    Memcached简介及环境安装 author:SimpleWu 简介 Memcached是一个自由开源的,高性能,分布式内存对象缓存系统. Memcached是以LiveJournal旗下Danga ...

  5. 用flask实现的添加后保留原url搜索条件

    1.具体实现 #!usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask,render_template,request,r ...

  6. 1709: Fire or Retreat(zzuli)

    水题,哎,可是第一次是因为编译错了,vs不知咋了,无奈: 后面几次又因为类型用了int错了,痛苦: 题目描述 在与科技水平远胜于我们的外星人的战斗最后,我们能够用来对外星装甲造成伤害的武器只剩下了…… ...

  7. 解决npm install过程中报错:unable to verify the first certificate

    今天使用npm安装开发包时遇到“unable to verify the first certificate”(无法验证第一证书)这个问题 原因:2014年2月27日,npm不再支持自签名证书.因为n ...

  8. hdu3586 树形dp+二分答案

    /* dp[i]表示孤立i结点的费用,二分功率上限w,即dp[i]在选择时不可以选择功率大于w的边 */ #include<bits/stdc++.h> using namespace s ...

  9. Linux下source命令详解

    source命令用法 source FileName source命令作用 在当前bash环境下读取并执行FileName中的命令. *注:该命令通常用命令“.”来替代. 使用范例: source f ...

  10. 解决beego中同时开启http和https时,https端口占用问题

    在beego的app.go文件中, 找到 // run normal mode if BConfig.Listen.EnableHTTPS { go func() { time.Sleep( * ti ...