题意:
给出n个正整数的序列,要求你找出符合sum(a1 + a2 + a3 + … + an) * min(a1,a2,…,an)的最大值,如果有多个符合条件的,输出最短序列.最短序列这点很重要。
分析:
那就设两个数组,纪录已当前数位最小值所能覆盖的最大区间,然后枚举每个数,求出区间和再乘上当前数求得值再进行比较 .设置左右区间时,可以递归比较,假设l[i]纪录的时ai所能覆盖的最左端点,如果aj <= ai (j > i),那么l[j] = l[i]了,然后再不断的更新找寻即可.
注意:sum数组,最大值要用long long。递归时l[i]从1-n,r[i]从n-1.不然会超时。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000010;
int n;
int num[maxn];
int l[maxn],r[maxn];
long long sum[maxn];
int main()
{
int cas=0;
while(scanf("%d",&n)!=EOF)
{
if(cas)
printf(" ");
cas++;
int i;
sum[0]=0;
memset(num,-1,sizeof(num));
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum[i]=sum[i-1]+num[i];
l[i]=i;
r[i]=i;
}
for(i=1;i<=n;i++)
{
while(num[l[i]-1]>=num[i])
l[i]=l[l[i]-1];
}
for(i=n;i>=1;i--)
{
while(num[r[i]+1]>=num[i])
r[i]=r[r[i]+1];
}
long long MAX=0;
int l1=1,r1=1;
long long sum1;
for(i=1;i<=n;i++)
{
sum1=(sum[r[i]]-sum[l[i]-1])*num[i];
if(sum1>MAX||(sum1==MAX&&(r1-l1>r[i]-l[i])))
{
MAX=sum1;
l1=l[i];
r1=r[i];
}
}
printf("%lld %d %d ",MAX,l1,r1);
}
}