51Nod 1437 单调栈

题目链接


题意:
有n个数,问对于每一个长度为x的连续区间内最小数,最大值为多少?
x[1,n],输出n个数,分别代表x=i时的答案。


思路:
考虑每一个数对答案的贡献。

使用单调栈,求出第i个数向左第一个比它小的数的坐标L[i]和向右第一个比它小的数的坐标R[i],则区间最小值为a[i]的最大区间长度len为:

len=R[i]L[i]1

注意到如果存在长度为len的区间包含a[i],则一定存在一个区间长度为len1的区间包含a[i],故对于答案数组从右到左线性扫描,每一个数与其右边的数取一个最大值即可。

时间复杂度:O(n)


#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;

const int A = 1e6 + 10;
int a[A],S[A],L[A],R[A],Ans[A],tot;

int main(){
    int n;
    scanf("%d",&n);

    for(int i=1 ;i<=n ;i++){
        scanf("%d",&a[i]);
    }

    tot = 0;
    for(int i=1 ;i<=n ;i++){
        while(tot>0 && a[S[tot]]>=a[i]){
            tot--;
        }

        if(!tot) L[i] = 0;
        else     L[i] = S[tot];

        S[++tot] = i;
    }

    tot = 0;
    for(int i=n ;i>=1 ;i--){
        while(tot>0 && a[S[tot]]>=a[i]){
            tot--;
        }

        if(!tot) R[i] = n+1;
        else     R[i] = S[tot];

        S[++tot] = 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-1 ;i>=1 ;i--){
        Ans[i] = max(Ans[i],Ans[i+1]);
    }

    for(int i=1 ;i<=n ;i++){
        printf("%d%c",Ans[i],i==n?'\n':' ');
    }
    return 0;
}
阅读更多
版权声明:新博客地址: dengxinhao.com 该博客只用于整理解题报告 https://blog.csdn.net/WuBaizhe/article/details/79958489
文章标签: Wubaizhe
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭