cf547 B. Mike and Feet(单调栈)
题意:
给定一个数组,对所有的长度 \(len\),输出 “所有长为 \(len\) 的区间中的最小值” 的最大值。
思路:
用单调栈求出包含 \(a_i\) 的、长度最大的、其中的所有数都大于等于 \(a_i\) 的区间 \([l_i,r_i]\)。
这意味着对于 \(len\le l_i-r_i+1\), \(ans[len]\ge a_i\)
长度越小,答案越大,最后每个答案要跟它的后继取max
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, a[N], stk[N], tt, l[N], r[N];
int ans[N];
signed main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
tt = 0, stk[++tt] = 0, a[0] = 0;
for(int i = 1; i <= n; i++)
{ //a[i]的左边第一个小于a[i]的数的右
while(a[stk[tt]] >= a[i]) tt--;
l[i] = stk[tt] + 1;
stk[++tt] = i;
}
tt = 0, stk[++tt] = n+1, a[n+1] = 0;
for(int i = n; i >= 1; i--)
{ //a[i]的右边第一个小于a[i]的数的左
while(a[stk[tt]] >= a[i]) tt--;
r[i] = stk[tt] - 1;
stk[++tt] = i;
}
for(int i = 1; i <= n; i++)
{
int len = r[i] - l[i] + 1;
ans[len] = max(ans[len], a[i]);
}
for(int i = n; i >= 1; i--) ans[i] = max(ans[i], ans[i+1]);
for(int i = 1; i <= n; i++) printf("%d ", ans[i]);
return 0;
}

浙公网安备 33010602011771号