51Nod-1437 迈克步(单调栈)

题意

n 个数字,定义区间的“力量”为区间最小数的值,对于每一个长度的区间,求这些区间力量的最大值。
1 n 2 × 10 5

思路

同样求每个数向左向右第一个比它小的数即可。然后更新以这个数作为力量的区间最大的长度的答案。最后输出结果是把大区间的值传给小区间并取 m a x 即可。

代码

由于这题比较卡语言,就用 C 语言交了。

#include<stdio.h>
#define FOR(i,x,y) for(i=(x);i<=(y);++i)
#define DOR(i,x,y) for(i=(x);i>=(y);--i)
int a[200003],L[200003],R[200003],ans[200003];
int stk[200003],n,i;
int max(int a,int b){return a>b?a:b;}

int main()
{
    scanf("%d",&n);
    FOR(i,1,n)scanf("%d",a+i);
    int top=0;
    a[0]=-2e9,stk[0]=0;
    FOR(i,1,n)
    {
        while(a[i]<=a[stk[top]])top--;
        L[i]=stk[top]+1;
        stk[++top]=i;
    }
    a[n+1]=-2e9,stk[top=0]=n+1;
    DOR(i,n,1)
    {
        while(a[i]<=a[stk[top]])top--;
        R[i]=stk[top]-1;
        stk[++top]=i;
    }
    FOR(i,1,n)ans[R[i]-L[i]+1]=max(ans[R[i]-L[i]+1],a[i]);
    DOR(i,n-1,1)ans[i]=max(ans[i],ans[i+1]);
    FOR(i,1,n-1)printf("%d ",ans[i]);
    printf("%d\n",ans[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Paulliant/article/details/81075794