zoukankan      html  css  js  c++  java
  • hdu1506

     题目大意: 一个横轴等距且为1的直方图,直方图总长为n,现给出每一列上的纵坐标hi(0 <= hi <= 1000000000)。求出直方图包含的面积最大的矩形的面积。

       解题思路:枚举起点i,找以高为height[i]的最大矩形,假设右边界最远到达di,那么ans=max{(di+1-i)*height[i] | i=1,2,3……n} (**)。当然不能裸着去暴力找每个di,那样的效率接近n^2。不难发现一些隐藏条件(i<j):

    1. 如果height[j]<height[i],那么di < j。这就意味着两个信息:
      1. 如果j是从i递增第一个搜索到的值,那么di=j
      2. (dj+1-j)*height[j]肯定也不是最优解,因为(dj+1-i)*height[j](从i开始以height[j]为高找矩形,貌似这个式子不在(**)中,但是如果更新height[i]=height[j]就不一定了)比它更优。
    2. 如果当前答案ans >= (n+1-i)*height[i],不管di是多少,它肯定不是最优解

      这样思路是不是就很好想了,用一个队列记录所有当前可选的i,又由于队列中的i,j没有height[j] < height[i] (i < j),故que中记录单调非递减的可能解。这个就叫单调队列

      看代码:(初学者可以试试自己做样例,看看注解代码里的输出信息)

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 #define f(head,i) height[que[head]]*(i-que[head]) //矩形[que[head],i-1]的面积
     7 typedef long long lli;
     8 lli height[1001000];
     9 int que[10010000];
    10 int main()
    11 {
    12     int n,head,tail;
    13     while(scanf("%d",&n) && n > 0){
    14         for(int i=1;i<=n;i++)
    15             scanf("%lld",&height[i]);
    16         lli ans=0;
    17         head=tail=0;
    18         que[tail++]=1;
    19         int n1=n+1; height[n1]=0;
    20         for(int i=2;i<=n1;i++){
    21             while(head+1<tail && f(head,n1)<=ans) //队列中至少有一个值,避免了队列为空时的特判
    22                 head++;
    23             ans = max(ans,f(head,i));
    24 /*
    25             printf("
    %d  ans = %lld
    ",i,ans);
    26             cout<<"que : "; for(int j=head;j<tail;j++) cout<<que[j]<<" "; cout<<endl;
    27             cout<<"hei : "; for(int j=head;j<tail;j++) cout<<height[que[j]]<<" "; cout<<endl;
    28 */
    29             while(head+1<tail && height[i]<=height[que[tail-2]])
    30                 tail--, ans = max(ans,f(tail,i));
    31             if(height[i]<=height[que[tail-1]])
    32                 ans = max(ans,f(tail-1,i)),height[que[tail-1]]=height[i];
    33             else
    34                 que[tail++]=i;
    35 /*
    36             printf("%d  ans = %lld
    ",i,ans);
    37             cout<<"que : "; for(int j=head;j<tail;j++) cout<<que[j]<<" "; cout<<endl;
    38             cout<<"hei : "; for(int j=head;j<tail;j++) cout<<height[que[j]]<<" "; cout<<endl;
    39 */
    40         }
    41         cout<<ans<<endl;
    42     }
    43     return 0;
    44 }
    View Code
  • 相关阅读:
    c++ 异常处理(2)
    ajax跨域,这应该是最全的解决方案了
    浏览器Request Header和Response Header的内容
    devDependencies和dependencies的区别
    json对象按时间排序
    JavaScript里的循环方法总结
    json list数据递归生成树状层级JSON
    javaScript年份下拉列表框内容为当前年份及前后50年
    vue cli+axios踩坑记录+拦截器使用,代理跨域proxy
    使用vue2+Axios+Router 之后的总结以及遇到的一些坑
  • 原文地址:https://www.cnblogs.com/karlvin/p/3291288.html
Copyright © 2011-2022 走看看