Bakery (USACO Silver 2023 February)
对总共花费的 moonies 数 进行二分, 表示花在 cookies 上的数量, 表示花在 muffins 上的数量。
有 。
我们有如下约束:
- (做每个cookie的时间严格大于0)
- (做每个muffin的时间严格大于0)
- (每个朋友的等待时间内做完)
所以对于每个 ,我们可以为 生成一个最小和最大可行范围,判断是否存在可行解。
注意在二分判断时,ceil 和 floor 的使用要小心。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll T, n, tc, tm;
ll a[100005], b[100005], c[100005];
ll xmin, xmax;
int main() {
scanf("%lld", &T);
while (T--) {
scanf("%lld %lld %lld", &n, &tc, &tm);
for (int i = 0; i < n; i++) {
scanf("%lld %lld %lld", &a[i], &b[i], &c[i]);
}
ll l = 0, r = tc+tm-2;
while (l < r) {
ll mid = (l+r)/2;
bool ok = true;
xmin = max(0LL, mid-tm+1); // 0 <= s-x <= tm-1
xmax = min(tc-1LL, mid);
for (int i = 0; i < n; i++) {
// (a[i]-b[i])x >= a[i]tc + b[i]tm -b[i]s - c[i]
ll numerator = a[i]*tc + b[i]*tm - b[i]*mid - c[i];
ll denominator = a[i]-b[i];
if (denominator > 0) {
xmin = max((ll)ceil((double)numerator/denominator), xmin);
} else if (denominator < 0) {
xmax = min((ll)floor((double)numerator/denominator), xmax);
} else {
if (a[i]*tc + b[i]*tm - b[i]*mid - c[i] > 0)
ok = false;
}
}
if (xmin > xmax) ok = false;
if (ok) r = mid;
else l = mid+1;
}
printf("%lld\n", l);
}
return 0;
}