zoukankan      html  css  js  c++  java
  • Hrbust-2352 Save the Little Ant

    这里写图片描述

    1e5的数据量,一开始想的一层一层遍历高度作差肯定会超时,只能做线性的O(n)扫描。
    因此这么想,要算积水,那么肯定有左右两个边界使其成为“凹”型,那么复杂的情况是,这个“凹”型不好找,如何确定整个图形的边界位置,可能凹中带凹,可能几个坑是分开的。这样一来就会不止扫一次才能找到这样图形。
    于是,我们可以找到整个图形中的最高点作为图形的分界线,将其分为左右两部分,分开各扫一遍,这样只需O(n)的复杂度。
    计算水体积时,从一边向中间扫,找到较大值时,将其记录,找到比记录的值小的值时,与记录的值作差即可得到这个“凹”处的体积。因为有了中央最高处作坑的其中一个固定边界,这样只需要遍历找到另一个边界,即可得到低处与较高处的差值。因为是由内而外的遍历,这样先找到的较大值就会围住比较大值小的低处。必定形成坑。左右遍历后得到的差值之和便是总的积水体积。

    #include<stdio.h>
    int main()
    {
        int a[100005],n;
        while(scanf("%d",&n)!=EOF)
        {
            long long Max=0,maxi=0,ans=0;///坑点,地平线是0,所以负数都是坑,不管边缘(第一个和最后一个数)是谁都算凹下去的
            for(int i=0; i<n; i++)///最坏情况是2e5*1e5,要用long long
            {
                scanf("%d",&a[i]);
                if(a[i]<0)ans+=-a[i],a[i]=0;///找到一个序列中最大值的位置,然后左右向这个最大值的位置扫
                if(a[i]>Max)///每次更新左右扫进去的最大值,如果大于最大值,更新最大值,否则减去,算坑,这样就把其中一个边界都作为最大值,另一个左右的边界是会更新变化的最大值
                {
                    Max=a[i];
                    maxi=i;
                }
            }///整个序列的最大值不在计算范围内,因为他作为了边界
            int maxx=0;
            for(int i=0; i<maxi; i++)
                if(a[i]>maxx)maxx=a[i];
                else ans+=maxx-a[i];
            maxx=0;
            for(int i=n-1; i>maxi; i--)
                if(a[i]>maxx)maxx=a[i];
                else ans+=maxx-a[i];
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    2017.4.18下午
    2017.4.18上午
    2017.4.17上午
    2017.4.14下午
    2017.4.14上午
    4.17下午
    4.17上午
    4.13下午
    4.13上午
    4.10上午
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11794310.html
Copyright © 2011-2022 走看看