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;
}

posted @ 2021-12-27 21:39  Bellala  阅读(58)  评论(0)    收藏  举报