UVALive 7501 Business Cycle(二分,xjb乱判)

题意:

给出每个关卡的得分。每次过关都加上当前的的关卡分数,如果小于0就变为0.

思路:

手动出了无数组样例, debug了一个多小时。。。T-T终于AC了

二分一个值,判断是否能够通过若干关后,满足要求。

二分判断条件:

1.如果跑一次,和跑两次,得分都是一样的,或者更小,那么必定有一个 相对于其他值来说是一个-inf的值,因此就在一圈,一圈~两圈之内跑。

2.如果不够跑两圈,那么也是在跑一圈之内,一圈到两圈之内跑。

3.如果够了两圈而且跑尽可能多的圈数合适,那么也有两种情况:

假如能跑n圈,以及mo个关卡

3.1    如果一个负值的洞出现在最接近结束的位置, 那么我们要判断n-1圈 + 跑1圈的最大值,以求避过那个负值

3.2    没什么好说的,就跑n圈和mo个关卡的最大值


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 50;

ll a[N], n, p, g;

ll cir(ll k){
	ll num = k;
	for(int i = 0; i < n; i++) {
		num += a[i];
		if(num < 0) num = 0;
	}
	return num;
}

ll cirmax(int pos, ll k){
	ll num = k, maxx = k;
	for(int i = 0; i < pos; i++){
		num += a[i];
		if(num < 0) num = 0;
		maxx = max(num, maxx);
	}
	return maxx;
}

bool judge(ll k){
	ll re1 = cir(k), ans = 0;
	ll re2 = cir(re1);
	if(re1 >= re2 || p < 2 * n) {
	//	cout << k << " " << 1 << endl;
		if(p > n ) {
            ans = max(ans, cirmax(n, k));
			if(p < 2 * n)ans = max(ans, cirmax(p - n, re1));
			else ans = max(ans, cirmax(n,  re1));
		}else{
            ans=max(ans,cirmax(p,k));
		}
	}else {
		ll times = p / n, mo = p % n;
		if((g - re1) / (re2 - re1) < times-1) return 1;
		ll sum2 = 0, sum1 = max(0LL, times - 1) * (re2 - re1) + re1;
		sum1 = cirmax(mo, sum1);
		sum2 = max(0LL, times - 2) * (re2 - re1) + re1;
		sum2 = cirmax(n, sum2);
		ans = max(ans, max(sum1, sum2));
	}
	return ans >= g;
}

int main(){
	int T;
	scanf("%d", &T);
	for(int kase = 1; kase <= T; kase++){
		scanf("%lld%lld%lld", &n, &g, &p);
		for(int i = 0; i < n; i++) scanf("%lld", &a[i]);
		ll l = 0, r = g, ans = g;
		while(l <= r) {
			ll mid = (l + r) / 2;
			if(judge(mid)) {
				ans = mid;
				r = mid - 1;
			}else l = mid + 1;
		}
		printf("Case #%d: %lld\n", kase, ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值