Building Blocks
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 281 Accepted Submission(s): 59
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.
Source
Recommend
hujie | We have carefully selected several similar problems for you: 5193 5192 5189 5188 5185
题意:有n堆由1*1小木块堆起来的积木,现在要你移动若干次使其中连续的长度为w的高度都为h,一次只能移动一个,而且可以在两边增加新堆(只能在两边,不能在中间插入),问最少得移动多少次。
思路:因为可以在两边增加堆,所以我先在数组两边各加上w长度,Move数组存 每个地方变成h要移进来或者移出去的步数,a数组记录i位子是要移进来还是移出去。然后维护一个长度为w的连续区间(i-w+1 ~ i),计算出这个区间总共得移进来的数目z和移出去的数目和f,那么要使这个区间满足条件就要移动m=z+f-min(z,f),(这里减去min(z,f)是因为移进来和移出去可以抵消一部分)。比赛时用的G++交的,结果终判超时挂了!后来用C++交就过了!!!
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 150010 #define MAXN 2005 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; ll n,w,h; ll Move[maxn]; bool a[maxn]; int main() { ll i,j,x; while (~scanf("%lld%lld%lld",&n,&w,&h)) { ll sum=0,m; FRL(i,0,n+2*w) a[i]=false; FRE(i,w+1,n+w) { scanf("%lld",&x); Move[i]=abs(h-x); if (h<x) a[i]=true; sum+=x; } if (w*h>sum) { pf("-1\n"); continue; } ll z=0,f=0; FRE(i,1,w) //前后扩大 Move[i]=h; FRE(i,n+w+1,n+2*w) Move[i]=h; z=w*h; f=0; m=z+f-min(z,f); ll ans=m; FRE(i,w+1,n+2*w) //枚举区间 { if (a[i-w]) //要除去前面一个区间的第一个数(往后移动它就出了嘛) f-=Move[i-w]; else z-=Move[i-w]; if (a[i]) //加上新进来的 f+=Move[i]; else z+=Move[i]; m=z+f-min(z,f); ans=min(ans,m); } pf("%lld\n",ans); } return 0; }