【POJ 2823 Sliding Window】 单调队列
题目大意:给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】 单调队列的更多相关文章
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- poj 2823 Sliding Window (单调队列入门)
/***************************************************************** 题目: Sliding Window(poj 2823) 链接: ...
- POJ 2823 Sliding Window (单调队列)
单调队列 加了读入挂比不加更慢.... 而且这份代码要交c++ 有大神G++跑了700ms..... orzorzorz #include<iostream> #include<cs ...
- poj 2823 Sliding Windows (单调队列+输入输出挂)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 73426 Accepted: 20849 ...
- POJ 2823 Sliding Window 题解
POJ 2823 Sliding Window 题解 Description An array of size n ≤ 106 is given to you. There is a sliding ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- POJ 2823 Sliding Window(单调队列入门题)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 67218 Accepted: 190 ...
- POJ 2823 Sliding Window 【单调队列】
题目链接:http://poj.org/problem?id=2823 题目大意:给出一组数,一个固定大小的窗体在这个数组上滑动,要求出每次滑动该窗体内的最大值和最小值. 这就是典型的单调队列,单调队 ...
- 【单调队列】poj 2823 Sliding Window
http://poj.org/problem?id=2823 [题意] 给定一个长度为n的序列,求长度为k的滑窗内的最大值和最小值 [思路] 裸的单调队列 注意用C++提交,不然会T,orz我用G++ ...
- 题解报告: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 ...
随机推荐
- Linux下的摄影后期处理软件
由于喜欢摄影,在LInux上折腾,想找一款能代替lightroom的软件.发现darktable这款软件专业.于是就安装了. 以下是在Linux上安装darktable的instruction,需要添 ...
- python list列表 方法总结
深入链表(most on lists) The list data type has some more methods. Here are all of the methods of list ob ...
- elasticsearch 搜索不支持单词的部分进行匹配
zjtest7-frontend:/usr/local/logstash-2.3.4/config# curl -XGET http://192.168.32.80:9200/logstash-201 ...
- 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 ...
- initial pointer [expert c]
initial differece between pointer and array Both arrays and pointers can be initialized with a liter ...
- android 分享到新浪微博
分享到新浪微博,折腾了大半个月,现在终于弄出来了,心里的那个爽呀,太痛快了,哈哈!! 废话少说,首先是认证, 1.进入新浪微博提供的开放平台注册新浪账号. 2.点击’我是开发者‘,创建一个应用,得到C ...
- Beauty of Array(模拟)
M - M Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit Status P ...
- [Android] 停止、恢复 背影音乐的播放
在执行录音操作时,我们希望可以将酷狗等后台播放的音乐停掉,在录音完成后再恢复播放,可以使用以下代码: /**@param bMute 值为true时为关闭背景音乐.*/ @TargetApi(Buil ...
- MVC学习 (二) Razor语法
MVC的Model层我理解与三层架构的Molde没有区别,都是作为各个层之间的数据沟通桥梁.但是关于Control和View都有一些与传统webform不同的特性. 这里先学习View里所用到的Raz ...
- 美化select的jquery插件
自己写的一个美化select插件,浏览器自带的实在太丑,还不能用css自定义. 插件主要原理是隐藏原生的select控件,支持select上设置change事件. 脚本 /* * iSelect * ...