POJ-2796-Feel Good(单调栈模板,区间最小*区间和,皆为非负数)

传送门

题意:一个序列内选一段区间,该区间值=区间长度*区间最小的数 ,使该值最大。且序列的数为非负数。
输出区间的左右端点和该区间的值(若有多种情况 随意输出一个)。

题解:维护一个单调递增栈。
(注意输入为 1 0时,ans初始化为负数不为0||ans<=cursum)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<stack>
#define en '\n'
using namespace std;
typedef long long ll;
const int N=1e5+5;
const ll INF=(ll)(1)<<(ll)(62);
ll a[N],sum[N],n;
stack<int>s;
void incr_stack()
{
    ll ans=-1,tmp,cursum;
    int dexl,dexr;
    for(int i=1;i<=n;i++)
    {
        if(s.empty()||a[i]>=a[s.top()])
            s.push(i);
        else
        {
            ll tmp,cursum;
            while(!s.empty()&&a[s.top()]>=a[i])
            {
                int dex=s.top();s.pop();
                tmp=s.empty()?sum[i-1]:(sum[i-1]-sum[s.top()]);
                cursum=a[dex]*tmp;
                if(ans<cursum)
                {
                    ans=cursum;
                    dexl=s.empty()?1:(s.top()+1),dexr=i-1;
                }
            }
            s.push(i);
        }
    }
    while(!s.empty())
    {
        int dex=s.top();s.pop();
        tmp=s.empty()?sum[n]:(sum[n]-sum[s.top()]);
        cursum=a[dex]*tmp;
        if(ans<cursum)
        {
            ans=cursum;
            dexl=s.empty()?1:(s.top()+1),dexr=n;
        }
    }
    printf("%lld\n%d %d\n",ans,dexl,dexr);
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
        incr_stack();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/89630631
今日推荐