Sitan Chen home

单调队列(Monotonic Queue)

17 Aug 2025

1.简介

2.实现

模版:洛谷P1886

对于长度为n的序列,有一个长度为k的窗口。窗口从左到右,每次滑动一个单位。求每次滑动后窗口内的最大值和最小值。


input
8  3
1  3  -1  -3  5  3  6  7


output
min -1 -3 -3 -3  3  3
max  3  3  5  5  6  7

思路:


for(int i = 1; i <= n; i++) { // 求最大值
		while(!q.empty() && q.front() < i - k + 1)
			q.pop_front();
		while(!q.empty() && a[q.back()] < a[i])
			q.pop_back();
		q.push_back(i);
  	maxi[i] = a[q.front()];
}


for(int i = 1; i <= n; i++) { // 求最小值
		while(!q.empty() && q.front() < i - k + 1)
			q.pop_front();
		while(!q.empty() && a[q.back()] > a[i])
			q.pop_back();
		q.push_back(i);
		mini[i] = a[q.front()];
}

3.变形

example 1: 洛谷P1714 求最大字段和 (给定了子段的长度为m)

题意: \(在\ p_n中,找出一个子段 [l,r]\ (r−l+1≤m),最大化 ∑_{i=l}^{r} \ p_i\) 与模版不同之处在于,此题需要求和,而非找到最值。因此需要使用前缀和。

用前缀和将序列处理完成之后,得到一个sum[]的数组,因此求[l,r]区间的和,可以用sum[r]-sum[l-1]来表示。

思路:

example 2: 洛谷P2216 (二维)

题意:

有一个 a×b 的整数组成的矩阵,现请你从中找出一个 n×n 的正方形区域,使得该区域所有数中的最大值和最小值的差最小。


input
a = 5, b = 4, n = 2
1   2   5   6
0   17  16  0
16  17  2   1
2   10  2   1
1   2   2   2


output
1

思路:

Total visits to this site: times