北大POJ上有一道单调队列的经典例题:模板题
本题大意是给出一个长度为 n的数组,编程输出每k个连续的数中的最大值和最小值。
最暴力的想法很简单,对于每一段的序列i ~ i+k-1,逐个比较来找出最大值(和最小值),时间复杂度约为O(n*k)
很显然,这其中进行了大量重复工作,除了开头k-1个和结尾k-1个数之外,每个数都进行了k次比较,而题中100%的数据为n<=1000000,当稍大的情况下,显然会 TLE。
这时所用到的就是单调队列了。
(1)概念:
顾名思义,单调队列的重点分为 “单调” 和 “队列”
“单调” 指的是元素的的 “规律”——递增(或递减)
“队列” 指的是元素只能从队头和队尾进行操作
Acwing_154滑动窗口
这道题目跟上面一道题目类似
AC代码:
#include<iostream>
using namespace std;
const int N = 1000010;
int n,k;
int a[N], q[N];
int main()
{
scanf("%d%d", &n,&k);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
int hh = 0, tt = -1;
for (int i = 0; i < n; i++) {
if (hh <= tt && i - k + 1 > q[hh]) hh++;
while (hh <= tt && a[q[tt]] >= a[i]) tt--;
q[++tt] = i;
if (i >= k - 1) printf("%d ", a[q[hh]]);
}
printf("\n");
hh = 0, tt = -1;
for (int i = 0; i < n; i++) {
if (hh <= tt && i - k + 1 > q[hh]) hh++;
while (hh <= tt && a[q[tt]] <= a[i]) tt--;
q[++tt] = i;
if (i >= k - 1) printf("%d ", a[q[hh]]);
}
system("pause");
return 0;
}