链接
传送门
题意
给出\(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; }
|