【Best Coder】#34 B Building Blocks

17 篇文章 0 订阅
9 篇文章 0 订阅

题目思路:首先按题解的要找出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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值