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

  • Post author:
  • Post category:其他



题目链接:




木材加工 – 洛谷



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;
}



版权声明:本文为bunny_1024原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。