Problem5753--学习系列——单调队列 I —— 构建单调递增队列

5753: 学习系列——单调队列 I —— 构建单调递增队列

[Creator : ]
Time Limit : 1.000 sec  Memory Limit : 256 MiB

Description

【知识点】
顾名思义,单调队列的重点分为 "单调" 和 "队列"。"单调" 指的是元素的的 "规律"——递增(或递减)。"队列" 指的是元素只能从队头和队尾进行操作。
例如原序列为:${1,\ 3,\ -1,\ -3,\ 5,\ 3,\ 6,\ 7}$。我们构造一个单调递增的队列会如下:
操作
队列状态
$1$入队
$\{1\}$
$3$比$1$大,$3$入队
$\{1\ 3\}$
$-1$比队列中所有元素小,所以清空队列$-1$入队
$\{-1\}$
$-3$比队列中所有元素小,所以清空队列$-3$入队
$\{-3\}$
$5$比$-3$大,直接入队
$\{-3\ 5\}$
$3$比$5$小,$5$出队,$3$入队
$\{-3\ 3\}$
$6$比$3$大,$6$入队
$\{-3\ 3\ 6\}$
$7$比$6$大,$7$入队
$\{-3\ 3\ 6\ 7\}$
特点: 可以快速取出最大值或最小值(队首元素)


单调队列一般有三步操作:
1、和普通队列不同,单调队列中插入元素的时候,要保证队列的单调性。
2、插入数据。
3、有不少题目对队列的空间有限制,插入数据后,还要维护队列的空间不超过限制。

在 OI 中,一般在单调队列中保存的是数组下标。数据保存在数组 a 中。

单调队列的实现,有两种方法。
方法一:使用 STL 的 双端队列 deque。
维护单调性
while (!que.empty() && a[que.back()]>=a[i]) {
    que.pop_back();
}

插入数据
que.push_back(i);

维护队列空间限制
while (que.size()>m) {
    que.pop_front();
}

方法二:使用数组
定义数据
const int MAXN=1e6+10;//数组大小要足够
int que[MAXN];//保存数据
int head=1;//头节点
int tail=0;//尾节点
维护单调性
while (head<=tail && que[tail]>=a[i]) {
    tail--;
}
入队
que[++tail]=i;
维护空间大小不操过m
while (head<=tail&&tail-head+1>m) {
    head++;
}



【任务】
给一个长度为 $n$ 的队列 $a$,请从头到尾输出对应的单调递增队列。

Input

第一行包括一个整数 $n\ (2 \leq n \leq 10^6)$,表示队列 $a$ 的大小。
第二行包括 $n$ 个整数 $-10^9 \leq a_i \leq 10^9$。

Output

一共 $n$ 行,每行若干个数。第 $i$ 行表示队列 $a_1,\ a_2,\ \dots,\ a_{i}$ 构成的单调递增队列。

Sample 1 Input

8
1 3 -1 -3 5 3 6 7

Sample 1 Output

1
1 3
-1
-3
-3 5
-3 3
-3 3 6
-3 3 6 7

Source/Category

数据结构 2.5.单调队列