题目大意:给n个数,一个长度为k(k<n)的闭区间从0滑动到n,求滑动中区间的最大值序列和最小值序列。

最大值和最小值是类似的,在此以最大值为例分析。

数据结构要求:能保存最多k个元素,快速取得最大值,更新时删去“过期”元素和“不再有希望”的元素,安放新元素。

单调队列的基本概念百度百科讲得比较清楚了:http://baike.baidu.com/view/3771451.htm

我的大致思路是:

1. 每个元素存储为结构体,包含它的秩和值。维护最大长度为k的单调队列,保证所有元素的秩都在区间内,且从首到尾的元素,秩递增,值递减。

2. 读入前k个元素(不存在过期问题),安放每个元素c:从队尾开始往回找到第一个大于它的元素g,将c放到g后面,c成为新的队尾

3. 队首赋给最大值序列的第一个值。

4. 读入k~n-1的元素,每读入一个元素c:

  (1)处理队首的过期元素(每次最多只可能是队首一个元素过期,因为队列长度不超过k,且秩是单调增的)

  (2)安放c(方法同前k个元素)

  (3)将新队首赋给最大值序列的下一个值

5. 输出最大值序列

想清楚了的话,代码还是比较好写的;队列没有封装,简单地用数组+首尾指针实现:

 #include <cstdio>
#include <cstring>
using namespace std; struct Node
{
int index;
int value;
}; Node max_q[],min_q[];
int max_res[],min_res[];
int front_max,front_min;//队首指针
int back_max,back_min;//队尾指针
int n,k,c; int main()
{
//freopen("c.txt","r",stdin);
scanf("%d%d",&n,&k);
back_max=back_min=front_max=front_min=;
scanf("%d",&c);
max_q[back_max].value=c;
min_q[back_min].value=c;
max_q[back_max].index=;
min_q[back_min].index=;//用第一个元素初始化
for(int j=;j<k;j++)//前k个元素
{
scanf("%d",&c);
while(back_max>= && max_q[back_max].value<=c) back_max--;
max_q[++back_max].value=c;
max_q[back_max].index=j; while(back_min>= && min_q[back_min].value>=c) back_min--;
min_q[++back_min].value=c;
min_q[back_min].index=j; }
max_res[]=max_q[].value;//区间起始位置的最值
min_res[]=min_q[].value; for(int j=k;j<n;j++)//下标为k到n-1的元素
{
scanf("%d",&c);
if(max_q[front_max].index==j-k) front_max++;
if(min_q[front_min].index==j-k) front_min++; while(back_max>=front_max && max_q[back_max].value<=c) back_max--;
max_q[++back_max].value=c;
max_q[back_max].index=j; while(back_min>=front_min && min_q[back_min].value>=c) back_min--;
min_q[++back_min].value=c;
min_q[back_min].index=j; max_res[j-k+]=max_q[front_max].value;//每读入一个元素,更新一次区间,得到一个最值
min_res[j-k+]=min_q[front_min].value;
} for(int j=;j<n-k+;j++)
printf("%d ",min_res[j]);
printf("\n");
for(int j=;j<n-k+;j++)
printf("%d ",max_res[j]);
printf("\n");
return ;
}

OJ的结果是这样的(G++会超时,尚不明原因):

最开始没有考虑过期的问题,考虑之后担心队列不够长,需不需要写成循环的;但稍加分析会发现,front指针后移只发生在删除队首过期元素时,最多只发生n-k次,那么数组开到2n就可以了。

由于是不循环的队列,只需front和back两个指针就可完成所有需要的操作。(之前因为和一个计数变量混用,并是在边界判断时WA了很多次)

把前k个元素和之后的元素分开处理是为了考虑方便,AC了之后试图把它们合并起来然后并是又WA了。。。看来有时候不必过于追求代码的简炼,初学还是清晰更重要。

【POJ 2823 Sliding Window】 单调队列的更多相关文章

  1. POJ 2823 Sliding Window + 单调队列

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

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

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

  3. POJ 2823 Sliding Window (单调队列)

    单调队列 加了读入挂比不加更慢.... 而且这份代码要交c++ 有大神G++跑了700ms..... orzorzorz #include<iostream> #include<cs ...

  4. poj 2823 Sliding Windows (单调队列+输入输出挂)

    Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 73426   Accepted: 20849 ...

  5. POJ 2823 Sliding Window 题解

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

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

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

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

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

  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++ ...

  10. 题解报告: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 ...

随机推荐

  1. Linux下的摄影后期处理软件

    由于喜欢摄影,在LInux上折腾,想找一款能代替lightroom的软件.发现darktable这款软件专业.于是就安装了. 以下是在Linux上安装darktable的instruction,需要添 ...

  2. python list列表 方法总结

    深入链表(most on lists) The list data type has some more methods. Here are all of the methods of list ob ...

  3. elasticsearch 搜索不支持单词的部分进行匹配

    zjtest7-frontend:/usr/local/logstash-2.3.4/config# curl -XGET http://192.168.32.80:9200/logstash-201 ...

  4. HDU1506(单调栈或者DP) 分类: 数据结构 2015-07-07 23:23 2人阅读 评论(0) 收藏

    Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  5. initial pointer [expert c]

    initial differece between pointer and array Both arrays and pointers can be initialized with a liter ...

  6. android 分享到新浪微博

    分享到新浪微博,折腾了大半个月,现在终于弄出来了,心里的那个爽呀,太痛快了,哈哈!! 废话少说,首先是认证, 1.进入新浪微博提供的开放平台注册新浪账号. 2.点击’我是开发者‘,创建一个应用,得到C ...

  7. Beauty of Array(模拟)

    M - M Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status P ...

  8. [Android] 停止、恢复 背影音乐的播放

    在执行录音操作时,我们希望可以将酷狗等后台播放的音乐停掉,在录音完成后再恢复播放,可以使用以下代码: /**@param bMute 值为true时为关闭背景音乐.*/ @TargetApi(Buil ...

  9. MVC学习 (二) Razor语法

    MVC的Model层我理解与三层架构的Molde没有区别,都是作为各个层之间的数据沟通桥梁.但是关于Control和View都有一些与传统webform不同的特性. 这里先学习View里所用到的Raz ...

  10. 美化select的jquery插件

    自己写的一个美化select插件,浏览器自带的实在太丑,还不能用css自定义. 插件主要原理是隐藏原生的select控件,支持select上设置change事件. 脚本 /* * iSelect * ...