51nod 1437 迈克步——单调栈

有n只熊。他们站成一排队伍,从左到右依次1到n编号。第i只熊的高度是ai。

一组熊指的队伍中连续的一个子段。组的大小就是熊的数目。而组的力量就是这一组熊中最小的高度。

迈克想知道对于所有的组大小为x(1 ≤ x ≤ n)的,最大力量是多少。

Input
单组测试数据。
第一行有一个整数n (1 ≤ n ≤ 2×10^5),表示熊的数目。
第二行包含n个整数以空格分开,a1, a2, ..., an (1 ≤ ai ≤ 10^9),表示熊的高度。
Output
在一行中输出n个整数,对于x从1到n,输出组大小为x的最大力量。
Input示例
10
1 2 3 4 5 4 3 2 1 6
Output示例
6 4 4 3 3 2 2 1 1 1

求出以每个元素为最小值的区间的左边界和右边界,保存下来,r[i] - l[i] +1 就是a[i]可作为最小值的区间的最大长度,然后这个长度的区间肯定包含这个长度-1的区间,于是依次取最大值。
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXSIZE 200005

using namespace std;

int a[MAXSIZE],l[MAXSIZE],r[MAXSIZE],s[MAXSIZE],ans[MAXSIZE];

int main()
{
    freopen("in.txt","r",stdin);
    memset(ans,0,sizeof(ans));
    memset(s,0,sizeof(s));
    int n,top;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    top = 0;
    for(int i=1;i<=n;i++) 
    {
        if(top==0)
        {
            s[++top] = i;
            l[i] = i;
        }

        else
        {
            while(top>=1 && a[s[top]]>=a[i])
            {
                top--;
            }
            if(top==0)
                l[i] = 1;
            else
                l[i] = s[top]+1;
            s[++top] = i;
        }
    }
    
    top = 0;
    for(int i=n;i>=1;i--)
    {
        if(top==0)
        {
            s[++top] = i;
            r[i] = i;
        }

        else
        {
            while(top>=1 && a[s[top]]>=a[i])
            {
                top--;
            }
            if(top==0)
                r[i] = n;
            else
                r[i] = s[top]-1;
            s[++top] = i;
        }
    }
    
    for(int i=1;i<=n;i++)
    {
        ans[r[i]-l[i]+1] = max(ans[r[i]-l[i]+1],a[i]);
    }
    for(int i=n-1;i>=1;i--)
    {
        ans[i] = max(ans[i+1],ans[i]);
    }
    for(int i=1;i<=n;i++)
    {
        if(i!=1) cout<<" ";
        cout<<ans[i];
    }
    return 0;
}

 

posted @ 2018-05-02 22:11  fantastic123  阅读(158)  评论(0编辑  收藏  举报