poj2796(继续学习单调栈)

//可以开一个单调递增栈,对于每一个新元素a[i]
//当前值小于等于栈顶元素,表示以栈顶元素为最小值的区间的右端是i
//栈顶元素a[j]出栈 , 由于是单调递增栈,新的栈顶元素a[k]必然小于a[j],故需要更新新的栈顶元素的
//右端值,新元素的左端的值也要更新为a[j]的左端
//一直重复操作直到栈顶元素大于新元素

//这样这个栈的每一个元素出栈时其左右区间必然是刚好最大的以该元素为最小值的区间

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define inf 0x3f3f3f3f
    #define maxn 100010
    #define LL long long
    using namespace std;

    int n;
    LL val[maxn], sum[maxn];
    int L[maxn], R[maxn];
    int sta[maxn];

    int main()
    {
        while(~scanf("%d", &n))
        {
            for(int i = 1; i <= n; i++) scanf("%lld", &val[i]), sum[i] = val[i];
            for(int i = 2; i <= n; i++) sum[i] += sum[i-1];

            int top = 0;
            for(int i = 1; i <= n; i++)
            {
                while(top > 0 && val[sta[top]] >= val[i]) top--;
                L[i] = top == 0 ? 1 : sta[top]+1;
                sta[++top] = i;
            }

            top = 0;
            for(int i = n; i >= 1; i--)
            {
                while(top > 0 && val[sta[top]] >= val[i]) top--;
                R[i] = top == 0 ? n : sta[top]-1;
                sta[++top] = i;
            }

            LL ans = -1, t;
            int ansi = 1;
            for(int i = 1; i <= n; i++)
            {
                t = val[i] * (sum[R[i]] - sum[L[i]-1]);
                if(ans < t) ans = t, ansi = i;
            }

            printf("%lld\n%d %d\n", ans, L[ansi], R[ansi]);

        }
        return 0;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值