您的位置:首页 > 其它

[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: