zoukankan      html  css  js  c++  java
  • HDU1506: Largest Rectangle in a Histogram(最大子矩阵,好题动态优化左右边界)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1506

    刚开始没考虑时间复杂度,直接敲了,直接tle了,之后没有思路,然后看题解,看见大神写的优化非常棒。

    大神的解释:(其实对于w[i]来说,如果去求后面连续的值,完全没必要一个个去比对,直接看w[i-1]的值就行了。

    比如说2、3、4、5这个序列,如果我们要看3往后能延伸多长,并不需要去逐个和4和5比较,在计算4的时候,我们已经计算过5是比4大的,因为3比4小,4所能往后延伸的长度,3也一定能达到(4能延伸的长度内的数据都大于等于4,当然也都比3大),我们可以直接比较在4达到的最终长度的末端之后的值。(dp进行记录)

    这道题计算的时候进制转换也需要特别注意,如果temp没有强制转换成__int64位,提交会wa。注意强制转换啊,否则wa.)

    这道题优化的思路非常巧妙,很值得学习。

    DP 找出 a[i] 的左边(l[i])和右边(r[i])与自己连着的比自己大的数的长度 , 然后用这个长度乘以 a[i], 乘积最大的那个就是答案 .

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #define inf 0x3f3f3f3f
    typedef __int64 ll;
    using namespace std;
    int n,w[100010],l[100010],r[100010];
    int main()
    {
        ll maxx,zan;
        while(scanf("%d",&n)!=EOF&&n!=0)
        {
            for(int i=1;i<=n;i++)
            {
              scanf("%d",&w[i]);
              l[i]=r[i]=i;
            }
            for(int i=2;i<=n;i++)
            {
                while(l[i]>1&&w[l[i]-1]>=w[i])
                {
                    l[i]=l[l[i]-1];
                }
            }
            for(int i=n-1;i>=1;i--)
            {
                r[i]=i;
                while(r[i]<n&&w[r[i]+1]>=w[i])
                {
                    r[i]=r[r[i]+1];
                }
            }
            maxx=-inf;
            for(int i=1;i<=n;i++)
            {
                zan=(ll)(r[i]-l[i]+1)*w[i];//以前一直对变量的存储有个错误的了解,如果(r[i]-l[i]+1)*w[i]
                maxx=max(maxx,zan);//如果不强制转换的话,则会wa,以后做题注意
            }
           printf("%I64d
    ",maxx);
        }
        return 0;
    }

    tle的水代码。

    include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #define inf 0x3f3f3f3f
    typedef __int64 ll;
    using namespace std;
    int n,w[100010];
    ll dp[100010];
    int main()
    {
        int minx;
        ll maxx,zan;
        while(scanf("%d",&n)!=EOF&&n!=0)
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&w[i]);
            memset(dp,0,sizeof(dp));
            dp[1]=w[1];
            maxx=w[1];
            for(int i=2;i<=n;i++)
            {
                minx=w[i];
                for(int j=i-1;j>=1;j--)
                {
                    minx=min(minx,w[j]);
                    zan=(i-j+1)*minx;
                    dp[i]=max(dp[i],zan);
                }
                maxx=max(maxx,dp[i]);
            }
            printf("%I64d
    ",maxx);
        }
        return 0;
    View Code
  • 相关阅读:
    Study Plan The TwentySecond Day
    Study Plan The Nineteenth Day
    Study Plan The TwentySeventh Day
    Study Plan The Twentieth Day
    Study Plan The TwentyFirst Day
    python实现进程的三种方式及其区别
    yum makecache
    JSONPath 表达式的使用
    oracle执行cmd的实现方法
    php daodb插入、更新与删除数据
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4381522.html
Copyright © 2011-2022 走看看