<题目链接>

<转载于>>> >

题目大意:

给你一段序列和一个长为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. Linux下Oracle 12c的卸载

    注:本文来源于:<Linux下Oracle 12c的卸载> 与Windows下Oracle的安装容易卸载麻烦相反,Linux下Oracle的安装麻烦下载简单. 1.关闭Oracle数据库 ...

  2. nginx代理跨域(mac)

    首先找到nginx.conf文件,修改并添加如下配置 html 文件 <!DOCTYPE html> <html lang="en"> <head&g ...

  3. 【python】多进程与mongo

    参考:http://api.mongodb.com/python/current/faq.html#using-pymongo-with-multiprocessing 如果使用了多进程,则必须在子进 ...

  4. MYSQL安装报错 -- 出现Failed to find valid data directory.

    运行环境:windows10数据库版本:mysql.8.0.12安装方式:rpm包直接安装 问题描述:mysql初始化的时候找不到对应的数据库存储目录 报错代码: 2018-10-13T03:29:2 ...

  5. Nginx详解九:Nginx基础篇之Nginx的访问控制

    基于IP的访问控制:http_access_module 不允许指定网段的用户访问:配置语法:deny address | CIDR | unix: | all;默认状态:-配置方法:http.ser ...

  6. Python老男孩

    1.可以自己编写模块,但注意:如果想要调用该模块,需要将该模块放到site-packages目录下,或将该模块放在执行程序的路径下. 2.pyc文件是什么? 集合: set 集合可以去重:做交集.并集 ...

  7. Python_网络编程udp-飞秋自动攻击

    # 模拟一个接收数据import socketimport time def auto_hack(udp_socket, recv_msg, revc_ip, revc_port=2425): # 发 ...

  8. NodeJs——router报错原因

    rout.js var http = require('http'); var url = require('url'); var router = require('./models/router. ...

  9. 【专栏学习】APM——异步编程模型(.NET不推荐)

    (1)learning hard C#学习笔记 异步1:<learning hard C#学习笔记>读书笔记(20)异步编程 (2)<C# 4.0 图解教程> 22.4 异步编 ...

  10. XShell发送命令到全部会话