hdu 1506 Largest Rectangle in a Histogram(DP)

题意:

有一个柱状图,有N条柱子。每一条柱子宽度都为1,长度为h1...hN。

在这N条柱子所构成的区域中找到一个最大面积,每平方米3块钱,问最多赚多少钱。

 

输入:

1<=N<=100000

0<=hi<=1000000000

 

思路:

N很大,肯定得用一个O(N)或O(NLOGN)的算法,,

假如这个面积的长是从第i条柱子到第j条柱子,宽则一定是第i条柱子到第j条柱子中最矮的那条柱子的高度。

而我们站在那根最矮的柱子向左看,第i-1条的柱子一定是小于当前柱子的,否则可以加进去。向右看同理。

所以了,咱们就枚举每一根柱子,把它当作一段区域中的最矮的那根,然后向左向右极大地去延伸。

具体如何延伸呢,

假设left[i]表示第i根向左最多延伸到的柱子编号

假设现在枚举到第k根柱子,如果第k-1根柱子高度小于本身,则向左没法延伸。如果大于等于,则从left[i-1]到i-1都是大于等于本身的,只需从left[i-1]-1开始继续往前比较,这里就可以用while循环实现了。

向右同理。

看代码,

 

代码:

int const N = 100005;

int h[N], leftt[N], rightt[N];


int main(){

    int n;
    while(cin>>n,n){

        mem(leftt,0);
        mem(rightt,0);

        rep(i,1,n){
            scanf("%d",&h[i]);
            leftt[i] = rightt[i] = i;
        }
        rep(i,2,n){
            if(h[i]<=h[i-1]){
                leftt[i] = leftt[i-1];
                while(leftt[i]>1 && h[i]<=h[leftt[i]-1]){
                    leftt[i] = leftt[leftt[i]-1];
                }
            }
        }
        rep2(i,n-1,1){
            if(h[i]<=h[i+1]){
                rightt[i] = rightt[i+1];
                while(rightt[i]<n && h[i]<=h[rightt[i]+1]){
                    rightt[i] = rightt[rightt[i]+1];
                }
            }
        }

        ll ans = 0;
        rep(i,1,n){
            ll temp = (ll)(rightt[i]-leftt[i]+1)*(ll)h[i];
            if(temp>ans) ans = temp;
        }

        printf("%I64d\n",ans);

    }

    return 0;
}

 

posted @ 2015-01-17 00:13  fish7  阅读(135)  评论(0编辑  收藏  举报