POJ 2823 Sliding Window
题目要求
给定n个数和大小为k的窗口,窗口每次移动一格输出窗口的最大值和最小值。
解题思路
利用单调队列的思想。在求窗口的最小值时,构建单调递增的队列,这样的队列的队首总是窗口的最小值。同理,构建单调递减的队列,队列的队首总是窗口的最大值。
和单调栈的区别是,单调队列不仅要维护单调性还要维护队列的大小,在这里就是必须确保队列的大小不能超过窗口的大小。
和单调栈一样,队列中保存的是元素的下标值。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
const int maxn = 1e6 + 5;
int n,k;
int a[maxn],q[maxn];
int main(void) {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
//构造单调递增的队列,队列中保存下标值
int l = 1, r = 0;//初始队列头尾指针 r-l+1=0
for (int i = 1; i <= n; i++) {
//维护队列的单调性
while (r >= l && a[q[r]] > a[i]) {
//如果队尾元素要小于当前的元素,将队尾元素弹出
r--;
}
//如果队尾元素大于当前元素,则当前元素入队列
q[++r] = i;
//维护队列窗口的大小
if (q[r] - q[l] + 1 > k) l++;
//输出最小值
if (i >= k) {
i == n ? printf("%d\n", a[q[l]]) : printf("%d ", a[q[l]]);
}
}
//构造单调递减的队列
l = 1, r = 0;
memset(q, 0, sizeof(q));
for (int i = 1; i <= n; i++) {
while (r >= l && a[q[r]] < a[i]) {
r--;
}
q[++r] = i;
if (q[r] - q[l] + 1 > k) l++;
if (i >= k) {
i == n ? printf("%d\n", a[q[l]]) : printf("%d ", a[q[l]]);
}
}
}