poj_2823 单调队列
2015-09-24 16:40
155 查看
题目大意
给定一行数,共N个。有一个长度为K的窗口从左向右滑动,窗口中始终有K个数字,窗口每次滑动一个数字。求各个时刻窗口中的最大值和最小值。题目分析
直接搜索,复杂度为O(n^2)。考虑使用单调队列,单调队列中的元素(或者元素的相关信息)单调递增或者递减。在本题中用一个单调递增的队列A保存当前窗口中值逐渐递增的索引,队列的头部元素为当前窗口中的最小值的索引;用一个单调递减的队列B保存当前窗口中值逐渐递减的索引,队列的头部元素为当前窗口中最大值的索引。窗口每移动到一个新的元素ele时,若新元素大于A中的队尾元素,则入队列,否则,不断弹出队尾的元素,直到队尾元素小于ele,然后入队;若新元素小于B的队尾元素,则入队列,否则,不断弹出队尾元素,直到队尾元素大于ele,然后入队。
若窗口移动到的最新元素的index - 队列头元素(队列中存放的是索引) > 窗口长度k,则队列头部后移,以保证队列中的索引位于窗口之内。
每个元素最多入栈2次,出栈2次,平摊复杂度为O(n).
单调队列/栈中存放的一般为序列元素的索引(可能还有其他更多信息),且每次新元素和队尾/栈顶元素比较,若满足单调性质,则入队/入栈;否则,不断弹出队尾/栈顶元素,直到满足单调性质,再入队/入栈。
有时可能还需要考虑栈和队列的size(如本题中的窗口)
实现(c++)
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #define MAX_SIZE 1000005 int gMaxInWindow[MAX_SIZE]; int gMinInWindow[MAX_SIZE]; int gIncQ[MAX_SIZE]; int gDecQ[MAX_SIZE]; int gArray[MAX_SIZE]; int main(){ int n, k; scanf("%d %d", &n, &k); int inc_front = 0, inc_tail = -1, dec_front = 0, dec_tail = -1; int ele; for (int i = 0; i < n; i++){ scanf("%d", &ele); gArray[i] = ele; while (inc_tail >= inc_front && gArray[gIncQ[inc_tail]] >= ele){ inc_tail--; } inc_tail++; gIncQ[inc_tail] = i; while (dec_tail >= dec_front && gArray[gDecQ[dec_tail]] <= ele){ dec_tail--; } dec_tail++; gDecQ[dec_tail] = i; if (i - gIncQ[inc_front] >= k){ inc_front++; } if (i - gDecQ[dec_front] >= k){ dec_front++; } if (i >= k - 1){ gMinInWindow[i - k + 1] = gArray[gIncQ[inc_front]]; gMaxInWindow[i - k + 1] = gArray[gDecQ[dec_front]]; } } for (int i = 0; i <= n - k; i++){ printf("%d ", gMinInWindow[i]); } printf("\n"); for (int i = 0; i <= n - k; i++){ printf("%d ", gMaxInWindow[i]); } return 0; }
相关文章推荐
- KETTLE安装部署及实例演示
- stl之string 常用函数 介绍
- 美瞳对眼睛的伤害
- spring声明式事务处理(hibernate)
- 研究pixhawk的makefile的结构(3)
- UnityShader实例16:屏幕特效之径向模糊(Radial Blur)
- 读《穷爸爸 富爸爸》
- 黑马程序员——Java语言基础:其他对象(System、Runtime、Date、Calendar、Math)
- tar解压问题gzip: stdin: not in gzip format
- iOS:KVO的概述与使用
- 【转】验证HTTP Referer字段
- pycharm乱码
- java构造器
- 心得分享:关于对Android的理解,知识点梳理
- MT6572 耳机驱动笔记
- ANR
- Yann LeCun:深度学习硬件前瞻
- 阿拉伯数字金钱转中文大写
- linux 进度条显示函数
- JS与Native交互