题意:一个序列内选一段区间,该区间值=区间长度*区间最小的数 ,使该值最大。且序列的数为非负数。
输出区间的左右端点和该区间的值(若有多种情况 随意输出一个)。
题解:维护一个单调递增栈。
(注意输入为 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();
}
}