ZOJ 4062 Plants vs. Zombies(二分+贪心) 2018ACM-ICPC青岛现场赛E

18 篇文章 0 订阅
16 篇文章 0 订阅

Plants vs. Zombies

题解:首先肯定可以想到走过去再回来是肯定浪费步数的,最多的只能是相邻的两个植物来回,大致就呈一个 Z Z Z字形走过,最后要注意最后一步停在哪里。其次最大化最小值,二分即可。(深深吐槽 % \% % 2000 m s 2000ms 2000ms刚好卡过 2333333 2333333 2333333,然后再交就 t l e tle tle,最后改成 c e i l ceil ceil才稳的)

代码

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 100100;
int a[N], n;
LL plant[N], m;
bool love(LL minH)
{
	memset(plant, 0, sizeof plant);
	for(int i = 1; i <= n; ++i) {
		if(m > 0) {
			plant[i] += a[i];
			m--;
		}
		if(m <= 0) break;
		if(plant[i] >= minH) continue;

		if(minH > plant[i]) {
			LL cnt = 1LL * ceil((minH - plant[i]) * 1.0 / a[i]);
			if(cnt * 2 <= m) {
				m -= cnt * 2;
				plant[i] += a[i] * cnt;
				plant[i + 1] += a[i + 1] * cnt;
			}else break;
			if(m <= 0) break;
		}
	}
	for(int i = 1; i <= n; ++i)
		if(plant[i] < minH) return 0;
	return 1;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int T;
	scanf("%d",&T);
	while(T--) {
		scanf("%d %lld",&n,&m);
		memset(a, 0, sizeof a);
		LL l = 1, r = 0, ans = 0, t = m;
		for(int i = 1; i <= n; ++i) {
			scanf("%d", a + i);
			r = max(r, a[i] * m);
		}
		if(m == 0) {
			puts("0");
			continue;
		}
		while(l <= r) {
			LL mid = l + (r - l) / 2;
			m = t;
			if(love(mid)) {
				ans = mid;
				l = mid + 1;
			}else{
				r = mid - 1;
			}
		}
		printf("%lld\n", ans);
	}

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值