[POJ 2823]Sliding Window[单调队列]
2016-03-09 13:48
197 查看
题目链接:[POJ 2823]Sliding Window[单调队列]
题意分析:
包含n个数字的数列,用一个长度为k的窗口移动从1开始向右移动,每次输出窗口中的最小值和最大值。分两行输出结果:最小值输出到上行,最大值输出到下行。
解题思路:
考虑每次移动窗口要进行的操作,总共有两种,增加一个数,删去一个数。考虑到需要涉及到删除操作,我们使用单调队列来进行维护。
L代表队列的左端,R代表队列的右端,以递增队列为例:
如果我们在队列中存储当前的值,那么整个删除操作会特别耗时。转换思路,考虑在队列中存放当前值的下标,而依靠值来排序。
那么队列左端第一个存储的下标,就是最小的值对应的下标。每次增加值从右端往左插入,如果队列中的那个值大于当前值,就可以直接丢弃(因为这个值出现的时间早于当前值,之后肯定不会成为最小值)。输出最小值的话,我们从左端往右端,第一个满足i - 下标 < k的值,就是我们要的满足条件的最小值。
个人感受:
存下标真是太机智了。
具体代码如下:
#include<stdio.h>
int a[1000100], q[1000100];
int main()
{
int n, k;
while (~scanf("%d%d", &n, &k)) {
int l = 0, r = 0, i, j;
for (i = 0; i < n; ++i) scanf("%d", &a[i]);
q[r] = 0;
for (i = 1; i < k; ++i) {
while (r >= 0 && a[q[r]] >= a[i]) --r;
q[++r] = i;
}
printf("%d", a[q[l]]);
for (i = k; i < n; ++i) {
while (r >= l && a[q[r]] >= a[i]) --r;
q[++r] = i;
while (i - q[l] >= k) ++l;
printf(" %d", a[q[l]]);
}
putchar('\n');
l = r = 0;
q[r] = 0;
for (i = 1; i < k; ++i) {
while (r >= 0 && a[q[r]] <= a[i]) --r;
q[++r] = i;
}
printf("%d", a[q[l]]);
for (i = k; i < n; ++i) {
while (r >= l && a[q[r]] <= a[i]) --r;
q[++r] = i;
while (i - q[l] >= k) ++l;
printf(" %d", a[q[l]]);
}
putchar('\n');
}
return 0;
}
题意分析:
包含n个数字的数列,用一个长度为k的窗口移动从1开始向右移动,每次输出窗口中的最小值和最大值。分两行输出结果:最小值输出到上行,最大值输出到下行。
解题思路:
考虑每次移动窗口要进行的操作,总共有两种,增加一个数,删去一个数。考虑到需要涉及到删除操作,我们使用单调队列来进行维护。
L代表队列的左端,R代表队列的右端,以递增队列为例:
如果我们在队列中存储当前的值,那么整个删除操作会特别耗时。转换思路,考虑在队列中存放当前值的下标,而依靠值来排序。
那么队列左端第一个存储的下标,就是最小的值对应的下标。每次增加值从右端往左插入,如果队列中的那个值大于当前值,就可以直接丢弃(因为这个值出现的时间早于当前值,之后肯定不会成为最小值)。输出最小值的话,我们从左端往右端,第一个满足i - 下标 < k的值,就是我们要的满足条件的最小值。
个人感受:
存下标真是太机智了。
具体代码如下:
#include<stdio.h>
int a[1000100], q[1000100];
int main()
{
int n, k;
while (~scanf("%d%d", &n, &k)) {
int l = 0, r = 0, i, j;
for (i = 0; i < n; ++i) scanf("%d", &a[i]);
q[r] = 0;
for (i = 1; i < k; ++i) {
while (r >= 0 && a[q[r]] >= a[i]) --r;
q[++r] = i;
}
printf("%d", a[q[l]]);
for (i = k; i < n; ++i) {
while (r >= l && a[q[r]] >= a[i]) --r;
q[++r] = i;
while (i - q[l] >= k) ++l;
printf(" %d", a[q[l]]);
}
putchar('\n');
l = r = 0;
q[r] = 0;
for (i = 1; i < k; ++i) {
while (r >= 0 && a[q[r]] <= a[i]) --r;
q[++r] = i;
}
printf("%d", a[q[l]]);
for (i = k; i < n; ++i) {
while (r >= l && a[q[r]] <= a[i]) --r;
q[++r] = i;
while (i - q[l] >= k) ++l;
printf(" %d", a[q[l]]);
}
putchar('\n');
}
return 0;
}
相关文章推荐
- Maven 安装
- PAT-Shuffling Machine (20)
- EnumSet源码分析
- Maven仓库管理之Nexus
- android开发时怎样让图片充满屏幕
- 标准爬虫初探,来自Python之父的大餐!
- Swift 学习有用的学习链接(此贴随学习的深入会一直更新)
- Java线程stop和suspend的废弃
- Windows server 2012 R2无法安装.net 3.5.1
- 个人iOS项目常用效果方法注意点集锦(上)----简书
- Windows server 2012 R2无法安装.net 3.5.1
- UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout
- 解决flash不能写入单个字节小记
- Dijkstra算法
- ScrollView嵌套GridView显示不全的解决办法
- VC6.0建立控制台程序实现PDA应用
- Java多线程:用三个线程控制循环输出10次ABC
- map::erase的使用
- PHP与Ajax的交互更新页面
- C#中枚举类型的使用