51nod 1437 迈克步 单调栈

利用单调栈高效的求出,一个数a[i]在哪个区间内可作为最小值存在。

正向扫描,求出a[i]可做为最小值的区间的左边界

反向扫描,求出a[i]可作为最小值的区间的右边界

r[i] - l[i] +1 就是a[i]可作为最小值的区间的 最大长度

我们知道:长度为len的区间,包含长度为len-1的区间

所以最后,需要逆向[确保无后效性]更新答案数组,保留最大值。

#include<stdio.h>
#include<math.h>
#include<cstring>
#include<stack>
#include<iostream>
#include<algorithm>
#include<queue>
#define MAXSIZE 200005
#define LL long long

using namespace std;
const int INF=999999999;

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

int main()
{
    memset(dp,0,sizeof(dp));
    memset(s,0,sizeof(s));
    int n,top;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&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++)
    {
        dp[r[i]-l[i]+1] = max(dp[r[i]-l[i]+1],a[i]);
    }

    for(int i=n-1;i>=1;i--)
    {
        dp[i] = max(dp[i+1],dp[i]);
    }

    for(int i=1;i<=n;i++)
    {
        printf("%d%c",dp[i],i==n?'\n':' ');
    }
    return 0;
}
View Code

 

posted @ 2018-01-30 10:14  声声醉如兰  阅读(181)  评论(0编辑  收藏  举报