题目思路:首先按题解的要找出w区间的方法,
我是用long long型的need和out,max(need,out)表示的就是这区间所要移动的积木的数量。
然后从左往右移动这个区间,可以发现, 当这个区间往下一个区间移动的时候,发生改变的只是头和尾的值。
所以这边我们就不需要重新计算了,只需要将尾减去,加上新进来头的值就可以得到新一个w区间的need和out
另外是处理新赠堆的情况。由于题目的要求,我们新增堆肯定是在左边或者右边。
比赛的时候我也是被hack掉了,没有考虑。
这边所采用的方法是事先就在左边加上w堆0的积木,右边也加上w堆0的积木。
这样假如需要新堆的话,那么在处理的时候就会包括。
AC代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int high[150500]{0};
int main()
{
int n, w, h;
while (~scanf("%d%d%d", &n, &w, &h))
{
long long sum = 0;
memset(high, 0, sizeof(high));
for (int i = w + 1; i <= w + n; i++)
{
scanf("%d", &high[i]);
sum += high[i];
}
long long mid = ((long long)w)*h;
if (sum < mid)
{
puts("-1");
continue;
}
long long out = 0;
long long need = mid;
long long ans = mid;
for (int i = w+1; i <= n + w+w; i++)
{
if (high[i-w] <= h)need -= h - high[i-w];
else out -= high[i-w] - h;
if (high[i] <= h)need += h - high[i];
else out += high[i] - h;
ans = min(ans, max(need, out));
}
printf("%lld\n", ans);
}
return 0;
}