Codeforces 547B Mike and Feet

链接

传送门

题意

给出$n(1 \leq n \leq 200000)$个整数,依次输出所有长度为$x(1 \leq x \leq n)$的连续子序列最小值的最大值。

思路

用单调队列求每个元素为最小的区间,然后对于每个长度求最小值的最大值。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
typedef long long LL;
using namespace std;
const int maxn = 200010;
int a[maxn], l[maxn], r[maxn];
priority_queue<int> q[maxn];
int ans[maxn];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
l[i] = 1;
r[i] = n;
}
deque<pair<int, int>> dq;
dq.push_back(make_pair(1, a[1]));
for (int i = 2; i <= n; ++i) {
while (!dq.empty() && dq.back().second > a[i]) {
r[dq.back().first] = i - 1;
dq.pop_back();
}
dq.push_back(make_pair(i, a[i]));
}
while (!dq.empty()) {
dq.pop_front();
}
dq.push_back(make_pair(n, a[n]));
for (int i = n - 1; i > 0; --i) {
while (!dq.empty() && dq.back().second > a[i]) {
l[dq.back().first] = i + 1;
dq.pop_back();
}
dq.push_back(make_pair(i, a[i]));
}
for (int i = 1; i <= n; ++i) {
int x = r[i] - l[i] + 1;
q[x].push(a[i]);
}
for (int i = n; i > 0; --i) {
ans[i] = max(ans[i + 1], q[i].empty() ? 0 : q[i].top());
}
for (int i = 1; i <= n; ++i) {
printf("%d ", ans[i]);
}
return 0;
}