单调队列
单调队列
概念
维护区间内单调的序列
滑动窗口
这道题队列维护的是数组的下标
[1 3 -1 -3 5 3 6 7],k 为 3.
下面我们来求最小值
i = 0, 队列为空,1入队
i = 1, 3大于1,3入队
i = 2, -1小于3,不满足单调递增,1,3出队, -1入队,这时满足k=3的条件,输出队首-1
i = 3, -1大于-3,不满足单调递增,-1出队,-3入队, 输出 -3
i = 4, 5大于-3, 5入队,此刻最小值还是-3
i = 5, 3小于5,不满足单调递增,5出队, 3入队, 输出-3
i = 6, 6大于3, 6入队, 此时 -3的下标是3, i = 6, 超出了窗口的范围,弹出-3, 最小值为3
i = 7, 7大于6, 7入队,输出 3
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int qq[N], hh = 0, tt = -1, a[N];
int n, k;
int main()
{
cin >> n >> k;
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
for(int i = 0; i < n; i++)//找最小值是要维护单调递增序列
{
if(hh <= tt && i - k + 1 > qq[hh]) hh++;//如果队首超过窗口大小,则出队
while(hh <= tt && a[i] <= a[qq[tt]]) tt--;//如果序列中的元素大于等于入队的元素,直接出队,直至有单调性为止
qq[++tt] = i;//入队,保持单调性
if(i + 1 >= k)//如果当前位置已经满足窗口大小
printf("%d ", a[qq[hh]]);
}
hh = 0, tt = -1;
printf("\n");
for(int i = 0; i < n; i++)
{
if(hh <= tt && i - k + 1 > qq[hh])hh++;
while(hh <= tt && a[i] >= a[qq[tt]]) tt--;
qq[++tt] = i;
if(i + 1 >= k)
printf("%d ", a[qq[hh]]);
}
return 0;
}

浙公网安备 33010602011771号