砍树--二分答案 审核通过

Horizon 摸鱼 2024-02-03 11:10:43 2024-02-03 12:52:40 25

二分答案的经典例题,分析题目先理清需要的变量。

变量 M 最少得到的木材高度  H 锯片高度  a[i] 每棵树的高
    a[i]-H 每棵树的木材  ans 得到的总木材  mx 最高的树高

在分析题目要求后,提取出以下信息。

1.计算得到的总木材长度
    1)锯片高于树高 -- ans += 0;
    2)锯片低于树高 -- ans += a[i]-h;

2.锯片的高度范围
    0~最高的树高 -- 0~mx
    题意要求尽量长的木材,举例特殊样例:
    样例输入:
    2 1
    1 100000
    这种情况下,取1段显然是100000最长,需要考虑到最大值的情况。

3.得到的总木材长需要大于等于需要的长度 -- ans >= k
    对于中间值这个点本身是否满足条件带来的结果需要注意一下。
    1)如果中间值满足条件,那么小于中间值的答案都舍弃。 -- l = mid;
    2)如果中间值不满足条件,那么大于等于中间值的答案都舍弃。 -- r = mid - 1;

那么根据以上的信息,我们可以写出二分模板。

int l=0, r=mx, mid, ans;
while (l<r) {
	mid = (l+r+1)/2;
	if (check(mid)) 
		ans = mid ,l = mid; //满足条件 舍弃比mid小的答案 
	else 
		r = mid-1;          //不满足条件  舍弃大于等于mid的答案 
} 

二分答案的精髓在于check函数,在本题中,我们要检查的是得到的总木材长和需要的木材长的比较。

bool check (int h) { //找到中间点后 计算得到的木材是否满足要求
	long long sum=0; //计算得到的总木材长 
	for (int i=1; i<=n; i++) {
		if (h>a[i]) 
			sum+=0;
		else 
			sum += a[i]-h;
	}
	return sum >= m; //返回是否满足条件 
}

注意!在这个题目的数据范围内,计算的结果会达到long long!

接下来只需要补全代码完成输入输出即可。

{{ vote && vote.total.up }}