《滑动窗口》

84 阅读1分钟

思路:用数组模拟单调栈,qh表示队头,qt表示队尾,从朴素算法中找到单调性的规律。

#include <bits/stdc++.h>

using i64 = long long;

const int N = 1000000;

int n, k;//表示数组长度和窗口的长度。
int a[N], q[N];//表示原数组和模拟队列的数组且队列数组里存的是原数组的下标。

int qh = 0, qt = -1;//表示队头下标和队尾下标。

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	std::cin >> n >> k;
	for (int i = 0; i < n; i++) {
		std::cin >> a[i];
	}

	for (int i = 0; i < n; i++) {
		if (qh <= qt && i - k + 1 > q[qh]) {
			qh++;
		}//判断队头元素是否弹出维护的区间。
		while (qh <= qt && a[q[qt]] >= a[i]) {
			qt--;
		}//解决队尾与当前元素a[i]不满足单调性的问题。
		q[++qt] = i;//进队。
		if (i >= k - 1) {
			std::cout << a[q[qh]] << " \n"[i == n - 1];//输出最小值。
		}
	}

	qh = 0, qt = -1;
	for (int i = 0; i < n; i++) {
		if (qh <= qt && i - k + 1 > q[qh]) {
			qh++;
		}//判断队头元素是否弹出维护的区间。
		while (qh <= qt && a[q[qt]] <= a[i]) {
			qt--;
		}//解决队尾与当前元素a[i]不满足单调性的问题。
		q[++qt] = i;//进队。
		if (i >= k - 1) {
			std::cout << a[q[qh]] << " \n"[i == n - 1];//输出最大值。
		}
	}

	return 0;
}