HDU 5191 Building Blocks
题目链接:
hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5191
bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=572&pid=1002
题解:
要在原始的n堆前面扩展w个空堆,同时在原始n堆后面扩展w个空堆,然后对[0,w+n+w)这个区间考虑所有的长度为w的子区间,计算出需要移动的方块数,更新答案。
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 typedef long long LL; 8 9 const int maxn = 50000+10; 10 11 int n; 12 LL w, h; 13 int arr[maxn*3]; 14 15 void init() { 16 memset(arr, 0, sizeof(arr)); 17 } 18 19 int main() { 20 while (scanf("%d%lld%lld", &n, &w,&h) == 3 && n) { 21 init(); 22 LL sum = 0; 23 for (int i = 0; i < n; i++) { 24 scanf("%d", arr + i+w); 25 sum += arr[i+w]; 26 } 27 if (sum < w*h) { 28 printf("-1\n"); 29 continue; 30 } 31 //cntf:总共需要填入多少个方块,cntz:总共需要移出多少个方块,cnt保存连续w个的初始和 32 LL cntz = 0,cntf=w*h, cnt = 0; 33 LL ans = w*h; 34 for (int i = w; i < 2*w+n; i++) { 35 //计算新窗口的cntz,cntf,cnt; 36 if (arr[i - w] - h>0) cntz -= (arr[i - w] - h); 37 else cntf -= (h - arr[i - w]); 38 cnt -= arr[i - w]; 39 if (arr[i] - h > 0) cntz += arr[i] - h; 40 else cntf += h - arr[i]; 41 cnt += arr[i]; 42 43 LL tmp; 44 if (w*h > cnt) tmp =cntf; 45 else tmp = cntz; 46 47 ans = min(ans, tmp); 48 } 49 50 printf("%lld\n", ans); 51 } 52 return 0; 53 }