[BestCoder #34]Building Blocks(乱搞)

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=5191

思路

比较fanjian的题目。。。因为G++交的话就会TLE。。。据说是HDU换了C11的编译器问题百出?
注意题目描述非常不清楚,不光可以把方块放在最右边的空地,也可以放在最左边的空地!!!我就是这样WA的!!!
因此我们在得到每堆方块的高度后,在所有方块的左边放W个高度为0的方块,右边放W个高度为0的方块。然后就是用两个指针维护一段长度为W的连续方块区间,并检查这段区间里的所有方块堆都变成高度为H的话最少要移动多少次,最优做法一定是先在这段区间内调整,高度大于H的堆往高度小于H的堆移动方块,然后再把还差的方块从外面移动进这段区间,或把还多的方块移动到外面。

其中需要对两个东西进行求和,可以维护这两个区间和的值,或者预处理出前缀和,均可以在每次移动区间后O(1)求得。

代码

1、前缀和版本

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 160000

using namespace std;

typedef long long int LL;

inline LL mymin(LL a,LL b)
{
    if(a>b) return b;
    return a;
}

inline LL myabs(LL x)
{
    if(x>0) return x;
    return -x;
}

LL h[MAXN],ans[MAXN],sum[MAXN];

int main()
{
    int n,W,H;
    while(scanf("%d%d%d",&n,&W,&H)!=EOF)
    {
        memset(h,0,sizeof(h));
        memset(ans,0,sizeof(ans));
        memset(sum,0,sizeof(sum));
        LL summ=0;
        for(int i=W+1;i<=n+W;i++)
        {
            scanf("%lld",&h[i]);
            summ+=h[i];
        }
        if(H*W>summ)
        {
            printf("-1\n");
            continue;
        }
        for(int i=1;i<=n+2*W;i++)
        {
            ans[i]=ans[i-1]+myabs(h[i]-H);
            sum[i]=sum[i-1]+h[i];
        }
        LL minans=0x7fffffff;
        for(int head=1,tail=W;tail<=2*W+n;head++,tail++)
        {
            LL anss=(ans[tail]-ans[head-1]+myabs(sum[tail]-sum[head-1]-H*W))/2;
            minans=mymin(minans,anss);
        }
        if(minans==0x7fffffff)
        {
            printf("-1\n");
            continue;
        }
        printf("%lld\n",minans);
    }
    return 0;
}

2、维护区间和的值版本

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 160000

using namespace std;

typedef long long int LL;

LL h[MAXN],ans[MAXN],sum[MAXN];

inline LL mymin(LL a,LL b)
{
    if(a>b) return b;
    return a;
}

inline LL myabs(LL x)
{
    if(x>0) return x;
    return -x;
}

int main()
{
    int n,W,H;
    while(scanf("%d%d%d",&n,&W,&H)!=EOF)
    {
        memset(h,0,sizeof(h));
        LL summ=0;
        for(int i=W+1;i<=n+W;i++)
        {
            scanf("%lld",&h[i]);
            summ+=h[i];
        }
        if(H*W>summ)
        {
            printf("-1\n");
            continue;
        }
        /*for(int i=1;i<=n+2*W;i++) { ans[i]=ans[i-1]+abs(h[i]-H); sum[i]=sum[i-1]+h[i]; }*/
        int head=1,tail=W,ans=0,sum=0;
        for(int i=head;i<=tail;i++)
        {
            ans+=myabs(h[i]-H);
            sum+=h[i];
        }
        LL minans=0x7fffffff;
        for(;tail<=2*W+n;head++,tail++)
        {
            LL anss=(ans+myabs(sum-H*W))/2;
            minans=mymin(minans,anss);
            ans-=myabs(h[head]-H);
            ans+=myabs(h[tail+1]-H);
            sum-=h[head];
            sum+=h[tail+1];
        }
        if(minans==0x7fffffff)
        {
            printf("-1\n");
            continue;
        }
        printf("%lld\n",minans);
    }
    return 0;
}

你可能感兴趣的:([BestCoder #34]Building Blocks(乱搞))