题意:给你n个数,让求某一连续子序列的和乘以其中子序列中的最小值的乘积最大.
分析:可以直接把每个数看成一个正方形,然后求这些正方形组合起来的最大矩形面积.可以单调栈解决这个问题,但是在计算的时候,要先求得前n项的和,找到每个数对应的区间之后,再利用尺取法求长度,最后求乘积,否则会TLE.
参考代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
ll n;
ll a[maxn];
ll l[maxn],r[maxn];
ll sum[maxn];
int main()
{
while( ~scanf("%lld",&n))
{
sum[0] = 0;
for( int i = 1; i <= n; i++)
{
scanf("%lld",&a[i]);
sum[i] = sum[i-1]+a[i];
// printf("sum=%lld\n",sum[i]);
}
stack<ll> s;
for( int i = 1; i <= n; i++)
{
while( !s.empty() && a[i] <= a[s.top()])
s.pop();
if( !s.empty())
l[i] = s.top()+1;
else
l[i] = 1;
s.push(i);
}
while( !s.empty())
s.pop();
for( int i = n; i >= 1; i--)
{
while( !s.empty() && a[i] <= a[s.top()])
s.pop();
if( !s.empty())
r[i] = s.top()-1;
else
r[i] = n;
s.push(i);
}
ll ans = 0;
ll p=1,q=1;
for( int i = 1; i <= n; i++)
{
ll tmp = (sum[r[i]]-sum[l[i]-1])*a[i];
// printf("l=%lld r=%lld suml=%lld sumr=%lld a=%lld tmp=%lld\n",l[i],r[i],sum[l[i]-1],sum[r[i]],a[i],tmp);
if( tmp > ans)
{
ans = tmp;
p = l[i];
q = r[i];
}
}
printf("%lld\n%lld %lld\n",ans,p,q);
}
return 0;
}