ACM - 牛客4743C - 三分
题意:中文题
思路:
三分。
对于(a,b),不妨设:A=2a+3b,B=4a+b
对于A装备来说,要想越多,那么消耗的b就很快。
对于B装备来说,要想越多,那么消耗的a就很快。
对于总数来说,A+B,那么一定存在“合理”分配,使得a和b的消耗比较平均。这个“合理”的方案,就是最大值,也就是三分中的极大值。
所以,用函数图像思考:
在左边,函数递增;在右边,函数递减。函数有极大值。
边界条件:
考虑:calc(ml) <= calc(mr)
首先注意这里一定带有等号,如果弄成 >= ,也一样
由于 ml 的函数值小,我们要求的是极大值,那么意味着,在[l,ml]的区间内,一定比 mr 的点小了,可以删去该区间,l = ml + 1
反之,同理
如果是求极小值,判断一致,赋值相反。代码如下。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x,y;
ll calc(ll xx){
return xx + min((x - 2 * xx) / 4, (y - 3 * xx));
}
int main(){
//freopen("input.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--){
scanf("%lld%lld", &x, &y);
ll l = 0, r = min(x / 2, y / 3), ans = 0;
ll tmp, ml, mr, mlans, mrans;
while(l <= r){
tmp = (r - l) / 3;
ml = l + tmp;
mr = r - tmp;
mlans = calc(ml);
mrans = calc(mr);
if (mlans <= mrans){
ans = max(ans, mlans);
l = ml + 1;
}
else{
ans = max(ans, mrans);
r = mr - 1;
}
}
printf("%lld\n", ans);
}
return 0;
}
补充一下:
有dalao的写法是这样,其实更合理:
while(l + 10 <= r){
...
}
for(int tmp = l; tmp <= r; tmp++){...}这样可以解决,这个函数不是完全单调递增的情况。
比如出现,3,3,4,4,4,4,5,5,5,6,5,5,5,5,4,4,1
这样的话,6一定会被算到。
这个10,相当于是最后选取了一个包含极大值的区间,然后每个计算。

查看23道真题和解析