DP:
用2个数组r[i],l[i]表示以第i个矩形的高度并包含这个矩形所组成的最大矩形的左右宽度的边界位置;
扩展左边界:
1。如果第j个矩型的高度比第i个矩阵(1<j<i)的高度低则做边界位置为i,即l[i]=j+1,终止;
2。如果高(或相等),则继续向左扩展,直到符合条件1。就终止。
扩展右边界:
类扩展左边界。
以下对于扩展左边界的解释:
n(100000)数据很大,如果用以下方法做(类似暴力吧),我们模拟一下发现,如果第j个矩阵扩展的左边界已经得到,在扩展其他第i(i>j)个矩阵时做了很多第j个矩阵扩展的操作,重复了,这样做 无疑 地TLE了;
此题用DP就可以避免重复扩展,当第j个矩形扩展到第第i个矩形时(j>i)此时无疑第i个矩形已经扩展好了。
1。如果第j个矩形的高度比第i个矩形低,l[i]=j+1,终止
2。如果高(或相等),直接把j的位置跳到l[j]的位置,直到符合条件1时终止。
另本题还要注意数据范围,要用__int64
//找以每个点为标准,向左延伸最远的位置
for(i=0;i<n;i++)
{
j=i;
while(j!=0&&a[j-1]>=a[i]) //找到a[j]<a[i]
j=l[j-1];
l[i]=j;
}
//找以每个点为标准,向右延伸最远的位置
for(i=n-1;i>=0;i--)
{
j=i;
while(j!=n-1&&a[j+1]>=a[i]) //找到a[j]<a[i]
j=r[j+1];
r[i]=j;
}
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 100050
long long l[maxn],r[maxn],a[maxn];
int main()
{
long long Max,n,i,j;
l[0]=0;r[0]=0;
while(scanf("%I64d",&n)!=EOF)
{
if(n==0) break;
for(i=0;i<n;i++)
scanf("%I64d",&a[i]);
//找以每个点为标准,向左延伸最远的位置
for(i=0;i<n;i++)
{
j=i;
while(j!=0&&a[j-1]>=a[i]) //找到a[j]<a[i]
j=l[j-1];
l[i]=j;
}
//找以每个点为标准,向右延伸最远的位置
for(i=n-1;i>=0;i--)
{
j=i;
while(j!=n-1&&a[j+1]>=a[i]) //找到a[j]<a[i]
j=r[j+1];
r[i]=j;
}
Max=0;
for(i=0;i<n;i++)
Max=max(Max,(r[i]-l[i]+1)*a[i]);
cout<<Max<<endl;
}
return 0;
}