Sliding Window
Time Limit: 12000MS   Memory Limit: 65536K
Total Submissions: 41844   Accepted: 12384
Case Time Limit: 5000MS

Description

An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example: 
The array is [1 3 -1 -3 5 3 6 7], and k is 3.

Window position Minimum value Maximum value
[1  3  -1] -3  5  3  6  7  -1 3
 1 [3  -1  -3] 5  3  6  7  -3 3
 1  3 [-1  -3  5] 3  6  7  -3 5
 1  3  -1 [-3  5  3] 6  7  -3 5
 1  3  -1  -3 [5  3  6] 7  3 6
 1  3  -1  -3  5 [3  6  7] 3 7

Your task is to determine the maximum and minimum values in the sliding window at each position.

Input

The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line. 

Output

There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values. 

Sample Input

8 3
1 3 -1 -3 5 3 6 7

Sample Output

-1 -3 -3 -3 3 3
3 3 5 5 6 7

双端队列介绍:

deque和vector一样都是标准模板库中的内容,deque是双端队列,在接口上和vector非常相似,在许多操作的地方可以直接替换。假如读者已经能够有效地使用vector容器,下面提供deque的成员函数和操作,进行对比参考。

deque<type>q;

q.empty():判断队列是否为空

q.front()  ,q.back()  队列的首元素和尾元素

q.begin() ,q.end() 返回队列首元素和结尾地址

q.push_front() ,q.push_back() 分别在队首和队尾插入元素

q.pop_front() ,q.pop_back() 删除首元素和尾元素

q.size() 返回容器中元素的个数

q.clear() 清空所有元素

本题最好采用模拟队列,缩短时限,分析怎样维护递增单调队列,开一个结构体要有id序号,和v值两个内容,首先当队列为空的时候,加入第一个元素;对于下一个将要加入的元素,把该元素a的大小和队尾的元素大小tail进行比较,如果a>tail,则移除尾元素,继续比较,直到a<=tail时把a加入到队列的尾部,当k个连续的数列向后移动时,队列中的前面的元素可能已经不再此范围内了,所以还要判断首元素的序号是不是在此时的范围内,如果不在,这删除首元素(即head++)直到满足条件为止,这样便可以维护一个单调递增队列

当维护单调递减序列的道理同上

程序:

#include"cstdio"
#include"cstring"
#include"cstdlib"
#include"cmath"
#include"string"
#include"map"
#include"cstring"
#include"algorithm"
#include"iostream"
#include"set"
#include"queue"
#include"stack"
#define inf 1000000000000
#define M 1000009
#define LL long long
#define eps 1e-12
#define mod 1000000007
#define PI acos(-1.0)
using namespace std;
int a[M],maxi[M],mini[M];
struct node
{
int v,id;
node(){}
node(int id,int v)
{
this->v=v;
this->id=id;
}
}qmin[M*2],qmax[M*2];
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=-1)
{
int minhead=0,mintail=0;
int maxhead=0,maxtail=0;
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i<=k)
{
while(mintail>minhead&&a[i]<qmin[mintail-1].v)
{
mintail--;
}
qmin[mintail++]=node(i,a[i]);//把前k个元素入队 while(maxtail>maxhead&&a[i]>qmax[maxtail-1].v)
{
maxtail--;
}
qmax[maxtail++]=node(i,a[i]);
}
}
mini[cnt]=qmin[minhead].v;
maxi[cnt++]=qmax[maxhead].v;
for(int i=k+1;i<=n;i++)
{
while(mintail>minhead&&a[i]<qmin[mintail-1].v)//删除比a[i]小的尾元素
{
mintail--;
}
qmin[mintail++]=node(i,a[i]);
while(mintail>minhead&&i-k>=qmin[minhead].id)//删除不再范围内的首元素
{
minhead++;
} while(maxtail>maxhead&&a[i]>qmax[maxtail-1].v)
{
maxtail--;
}
qmax[maxtail++]=node(i,a[i]);
while(maxtail>maxhead&&i-k>=qmax[maxhead].id)
{
maxhead++;
}
mini[cnt]=qmin[minhead].v;
maxi[cnt++]=qmax[maxhead].v;
}
printf("%d",mini[0]);
for(int i=1;i<cnt;i++)
printf(" %d",mini[i]);
printf("\n%d",maxi[0]);
for(int i=1;i<cnt;i++)
printf(" %d",maxi[i]);
printf("\n");
}
return 0;
}

  

双端队列(单调队列)poj2823 区间最小值(RMQ也可以)的更多相关文章

  1. Java数据结构——用双端链表实现队列

    //================================================= // File Name : LinkQueue_demo //---------------- ...

  2. POJ 2823 Sliding Window + 单调队列

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

  3. 与图论的邂逅01:树的直径&基环树&单调队列

    树的直径 定义:树中最远的两个节点之间的距离被称为树的直径.  怎么求呢?有两种官方的算法(不要问官方指谁我也不晓得): 1.两次搜索.首先任选一个点,从它开始搜索,找到离它最远的节点x.然后从x开始 ...

  4. Sliding Window - 题解【单调队列】

    题面: An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving fr ...

  5. [洛谷P1886]滑动窗口 (单调队列)(线段树)

    ---恢复内容开始--- 这是很好的一道题 题目描述: 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口. 现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的 ...

  6. POJ3162 Walking Race(树形DP+尺取法+单调队列)

    题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长. 各个结点到其他结点的最远距离可以用树形DP ...

  7. 51nod 1050 循环数组最大子段和 单调队列优化DP

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 这个呢,这个题之前 求一遍最大值  然后求一遍最小值 ...

  8. Second My Problem First HDU - 3706 单调队列

    单调队列 单调队列是指一个队列内部的元素具有严格单调性的一种数据结构,分为单调递增队列和单调递减队列. 单调队列满足两个性质 1.单调队列必须满足从队头到队尾的严格单调性. 2.排在队列前面的比排在队 ...

  9. P1886 滑动窗口 /【模板】单调队列 方法记录

    原题链接 滑动窗口 /[模板]单调队列 题目描述 有一个长为 \(n\) 的序列 \(a\),以及一个大小为 \(k\) 的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最 ...

随机推荐

  1. Python For Data Analysis -- NumPy

    NumPy作为python科学计算的基础,为何python适合进行数学计算,除了简单易懂,容易学习 Python可以简单的调用大量的用c和fortran编写的legacy的库 Python科学计算的这 ...

  2. scandir 使用示例

    int filter_fn(const struct dirent * ent) {     if (ent->d_type != DT_REG)         return 0;     r ...

  3. [daily][device] linux挂载iphone

    头几个月去旅游,亲戚的iphone照了好多照片,空间不足.就备份在了我的电脑上. 那么问题就是如何在linux系统里挂载iphone? 我找到了这篇文档,然而我没看. https://wiki.arc ...

  4. Bluetooth L2CAP介绍

    目录 1. 通用操作 1. L2CAP Channel 2. 设备间操作 3. 层间操作 4. 操作模式 2. 数据包格式(Data Packet Format) 1. B-Frame 2. G-Fr ...

  5. 软件工程概论---max单元测试

    题目:一个单元测试,查找list[]中的最大值 编写一个程序对Largest函数进行测试,列举所有测试用例. 思路:首先确保数组不为空,和数组长度不为0,否则输入错误.根据老师所给的函数写一个主函数, ...

  6. CentOS7+Redis Live安装配置

    Redis Live是一个用来监控redis实例,分析查询语句并且有web界面的监控工具,使用python编写. 代码下载地址:https://github.com/nkrode/RedisLive ...

  7. ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮)

    /** *  ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮) */ UIAlertController *al ...

  8. Windows-002-U盘启动盘制作

    通常我们安装系统时,均采用光盘的形式安装,只是这种方法需要随时随地的带着光盘,还不容易保存.携带光盘.这时,一个 U盘启动盘 就是您的首选了,此种方式的好处多多,比如:忘记开机密码.系统备份.安装系统 ...

  9. 如何将数据库中的表导成XML文件

    1.现将数据库中的信息读到DataTable中 2.用函数将DataTable转为string private string ConvertDataTableToXML(DataTable dt) { ...

  10. LintCode Subtree

    原题链接在这里:http://www.lintcode.com/en/problem/subtree/ You have two every large binary trees: T1, with ...