ACM模版

描述

题解

单调栈问题,直接一遍单调栈求出来每一个数作为最小值的区间范围,根据范围大小进行更新结果。

一开始我求出来每个值作为最小值的区间范围大小 x 后,我用了一个循环让他更新从 1x 的所有值,然后 TLE 了,后来发现,其实我们完全不用酱紫的,只要更新一下 x 的值,因为我们可以保证,最后输出的序列是一个单调不递增的序列,如果宽度为 x 的最大力量为 y ,那么宽度比 x 小的最大力量一定大于等于 y ,所以我们最后再倒着刷新一遍 ans 即可。

很容易就想到单调栈,但是后边这个刷新的过程一下子还真不容易想到。所以最开始 WA 了两发……辣鸡啊我~~(>_<)~~

对了,我发现有关单调栈的题的代码都好一样,这个代码是我直接拿 数组的宽度 那道题的代码改的……

代码

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stack>

using namespace std;

const int MAXN = 2e5 + 11;

struct num
{
    int value;
    int minLeft, minRight;

    num() : minLeft(1), minRight(1) {}
} A[MAXN];

int N;
int value, key;
stack<pair<int, int> > S;

void stackClear()
{
    while (!S.empty())
    {
        S.pop();
    }
}

void getMin()
{
    stackClear();

    S.push(make_pair(A[0].value, 0));
    for (int i = 1; i < N; i++)
    {
        while (!S.empty() && S.top().first >= A[i].value)
        {
            value = S.top().first;
            key = S.top().second;
            S.pop();

            A[i].minLeft += A[key].minLeft;
            if (!S.empty())
            {
                A[S.top().second].minRight += A[key].minRight;
            }
        }
        S.push(make_pair(A[i].value, i));
    }
    while (!S.empty())
    {
        key = S.top().second;
        S.pop();
        if (!S.empty())
        {
            A[S.top().second].minRight += A[key].minRight;
        }
    }
}

int ans[MAXN];

void solve()
{
    for (int i = 0; i < N; i++)
    {
        int t = A[i].minLeft + A[i].minRight - 1;
        ans[t] = max(ans[t], A[i].value);
    }
    for (int i = N - 1; i > 0; i--)
    {
        ans[i] = max(ans[i], ans[i + 1]);
    }
}

template <class T>
inline void scan_d(T &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

void Out(int a)
{    // 输出外挂
    if (a < 0)
    {
        putchar('-');
        a = -a;
    }
    if (a >= 10)
    {
        Out(a / 10);
    }
    putchar(a % 10 + '0');
}

int main(int argc, const char * argv[])
{
    scan_d(N);

    for (int i = 0; i < N; i++)
    {
        scan_d(A[i].value);
    }

    getMin();

    solve();

    for (int i = 1; i <= N; i++)
    {
        Out(ans[i]);
        putchar(' ');
    }
    putchar(10);

    return 0;
}