洛谷 P2440 木材加工(二分,含边界处理的笔记)

 题目链接:

木材加工 - 洛谷https://www.luogu.com.cn/problem/P2440

 非常简单的题目,用left和right控制二分边界,ans一开始是0,每次check到符合题意结果都更新ans的值,看起来没有任何问题。

但是我当时写的时候re了,看了半天也没看出问题。后来队友帮我debug,才发现是边界处理不到位。左边界left一开始设置成了0而不是1,导致了 /0的错误。

收获:

1.re不一定是数组越界,还有可能是 /0错误。

2.学习到了一些debug技巧,打印ans日志的时候,发现少输出了一个数,是因为最后一次ans计算的时候出现 /0错误,导致中断了,我由此发现了这个问题。

以下是修改之后的ac代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll len[maxn];
ll n, k;

bool check(int mid){
    ll ans = 0;
    for(int i=1; i<=n; i++){
        ans += len[i]/mid;
    }
    if(ans >= k) return true;
    else return false;
}
int main(){
    cin >> n >> k;
    //特别注意这里的left要设为1,不能是0,否则check函数中会出现 /0 的错误
    //右边界设为0没有关系,因为如果一直是0,后面进入不了while循环,不会出问题
    ll left = 1, right = 0;
    for(int i=1; i<=n; i++){
        cin >> len[i];
        right = max(right, len[i]);
    }

    ll ans = 0;
    while(left <= right){
        int mid = left + (right-left)/2;
        if(check(mid)) {left = mid+1; ans = mid;}
        else right = mid-1;
    }
    cout << ans << endl;
}

---------------------------------------------------------------------------------------------------------------------

第二天补充:也可以用 left < right 型二分, 省去ans变量,最后返回的就是left,但是这么写要注意特判,尽管left不能设置为0,但答案有可能是0。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll len[maxn];
ll n, k;

bool check(int mid){
    ll ans = 0;
    for(int i=1; i<=n; i++){
        ans += len[i]/mid;
    }
    if(ans >= k) return true;
    else return false;
}
int main(){
    cin >> n >> k;
    ll left = 1, right = 0;
    for(int i=1; i<=n; i++){
        cin >> len[i];
        right = max(right, len[i]);
    }

    if(!check(1)) {cout<<0<<endl; return 0;} //特判,输出0的情况
    while(left < right){
        int mid = left + (right-left+1)/2;
        if(check(mid)) {left = mid;}
        else right = mid-1;
    }
    cout << left << endl;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值