Building Blocks 区间枚举

来源:互联网 发布:java 多租户 编辑:程序博客网 时间:2024/05/16 17:07
Building Blocks
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1182 Accepted Submission(s): 262


Problem Description
After enjoying the movie,LeLe went home alone. LeLe decided to build blocks.
LeLe has already built n piles. He wants to move some blocks to make W consecutive piles with exactly the same height H.

LeLe already put all of his blocks in these piles, which means he can not add any blocks into them. Besides, he can move a block from one pile to another or a new one,but not the position betweens two piles already exists.For instance,after one move,"3 2 3" can become "2 2 4" or "3 2 2 1",but not "3 1 1 3".

You are request to calculate the minimum blocks should LeLe move.


Input
There are multiple test cases, about 100 cases.

The first line of input contains three integers n,W,H(1≤n,W,H≤50000).n indicate n piles blocks.

For the next line ,there are n integers A1,A2,A3,……,An indicate the height of each piles. (1≤Ai≤50000)

The height of a block is 1.


Output
Output the minimum number of blocks should LeLe move.

If there is no solution, output "-1" (without quotes).


Sample Input

4 3 2 1 2 3 5 4 4 4 1 2 3 4



Sample Output

1 -1
Hint

In first case, LeLe move one block from third pile to first pile.


枚举最终的W堆积木在哪,确定了区间,那么就需要把高于H的拿走,低于H的补上,高处的积木放到矮的上面,这样最优。因此把这个区间变成W*H的代价就是max(∑(Hi−H),∑(H−Hj))(Hi>H,Hj≤H)即在把高的变矮和把矮的变高需要的移动的积木数取较大的。从第一个区间[1,W]到第二区间[2,W+1]只是改变了2堆积木,可以直接对这两堆积木进行删除和添加来维护∑(Hi−H)和∑(H−Hj)。需要注意的是,最终选取的W堆积木中,有可能有几堆原本不存在。如 9 8 7 形成3*3,可把3堆积木变成5堆 3 3 3 8 7,最少移动6个积木。因此需要在n堆积木两端补上W个0。整个问题的复杂度是O(n+W).

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<map>using namespace std;const int maxn=50005*3;const int inf=200000;#define lson rt<<1,l,m#define rson rt<<1|1,m+1,rtemplate<class T>inline T read(T&x){    char c;    while((c=getchar())<=32);    bool ok=false;    if(c=='-')ok=true,c=getchar();    for(x=0; c>32; c=getchar())        x=x*10+c-'0';    if(ok)x=-x;    return x;}template<class T> inline void write(T x){    if(x<0)putchar('-'),x=-x;    if(x<10)putchar(x+'0');    else write(x/10),putchar(x%10+'0');}template<class T>inline void writeln(T x){    write(x);    putchar('\n');}///-------IO template------int a[maxn];typedef long long ll;int main(){    int n,m,i,j,k,t;    int w,h;    while(~scanf("%d%d%d",&n,&w,&h))    {        ll sum=0;        for(i=1;i<=w;i++)a[i]=0;        for(i=w+1; i<=n+w; i++)        {            read(a[i]);            sum+=a[i];        }        for(i=n+w+1;i<=n+w+w;i++)a[i]=0;        if(sum<(ll)w*h)        {            printf("-1\n");            continue;        }        ll ans2=0;        ll ans1=0;        ll ans=inf,rec=inf;        for(i=1; i<=w; i++)        {            if(a[i]>h)                ans1+=a[i]-h;            else                ans2+=h-a[i];        }        int first=1;        rec=ans=max(ans1,ans2);        for(i=w+1; i<=n+w+w; i++)        {            if(a[first]>h)                ans1-=a[first]-h;            else                ans2-=h-a[first];            if(a[i]>h)                ans1+=a[i]-h;            else                ans2+=h-a[i];            first++;        ans=max(ans1,ans2);        rec=min(ans,rec);        }        writeln(rec);    }    return 0;}


0 0
原创粉丝点击