poj -2559

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值