题目大意:给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. python连续爬取多个网页的图片分别保存到不同的文件夹

      python连续爬取多个网页的图片分别保存到不同的文件夹 作者:vpoet mail:vpoet_sir@163.com #coding:utf-8 import urllib import ur ...

  2. hdu 3478 Catch(染色 dfs 或 bfs )

    Problem Description A thief is running away! We can consider the city to N–. The tricky thief starts ...

  3. Easy Number Challenge(暴力,求因子个数)

    Easy Number Challenge Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I ...

  4. HDOJ 题目分类

    HDOJ 题目分类 /* * 一:简单题 */ 1000:    入门用:1001:    用高斯求和公式要防溢出1004:1012:1013:    对9取余好了1017:1021:1027:   ...

  5. Android 属性动画(Property Animation) 全然解析 (下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38092093 上一篇Android 属性动画(Property Animatio ...

  6. CCCardinalSplineBy概念

    cardianl 红衣主教 这个类是样条曲线动作, 其创建函数是CCCardinalSplineBy::create(float duration, cocos2d::CCPointArray *po ...

  7. Android 四大组件之 Activity

    1 简介 Activity (活动) 即应用程序 显示的 界面.可以通过两种方式 设置显示的内容 1:纯代码方式 2:xml 布局方式 无论哪一种方式,都是通过 setContentView 来设置显 ...

  8. 关于iOS多线程,你看我就够了

    在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇文章将会使 用 Swift  ...

  9. Zjnu Stadium(hdu3047带权并查集)

    题意:一个300列的无限行的循环场地,a b d代表a,b顺时针相距d的距离,现在给你一些距离,判断是否有冲突,如果有冲突计算冲突的次数 思路:带权并查集 a,b的距离等于b到根节点的距离 - a到根 ...

  10. thinkphp的条件的多种写法

    class SelectAction extends Action{   function index(){ //thinkphp 查询语言  //         1.普通查询 //   2.区间查 ...