二分答案区间划分与边界问题

对于二分答案来说, 他将整个答案划分为左右两个区间, 会有以下几个问题

  • 问题一:答案 mid 落在哪个区间?

    ​ 对此问题可以有两种区间的划分方式:

    • mid 落在左边,那么区间划分为 [l, mid][mid + 1, r]
    • mid 落在右边,那么区间划分为 [l, mid - 1][mid, r]
  • 问题二:到底选择哪种划分方式?

    ​ 严格来见,check 函数其实有三种结果,

    • res == mid,说明当前 mid 是答案
    • res < mid,说明 res 小了,答案在右边的区间
    • res > mid,说明 res 大了,答案在左边的区间

    举个例子,假如一道题限制是不超过100,若当前 mid = 98,而且我们不知道区间中到底有没有99100,那么虽然 98 < 100 属于第二种情况,但它可能是最终答案(并且我们仍然要继续循环,寻找一个更优解);

    若当前 mid = 101,其显然超过了限制,它一定不是答案,所以答案在其左边;在这个例子中,显然可以将 res == midres < mid 合并起来,那么 check 函数的返回结果可以是 res <= mid 也可以是 res > mid ,就是将这两个结果分配给两个区间,分配的方式就是看这个 = 号,等于号在哪边,哪边区间就包含 mid

  • 问题三:为什么会无限循环

​ 见例题代码

例题: C - Transportation Expenses (atcoder.jp)
例题代码:
void solve()
{
    int n;
    long long m;
    cin >> n >> m;

    vector<long long> a(n);
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }

    auto check = [&](long long mid) -> bool {
        long long s = 0;
        for(int i = 0; i < n; i++) {
            s += min(a[i], mid);
        }

        // 根据题意, 当 s == m 时, 说明当前补贴 mid 有可能是最终答案, 
        //          当 s < m 时, 说明 mid 小了, 答案在右边, 并且当前mid可能是最终答案
        //          当 s > m 时, 说明 mid 大了, 答案在左边, 并且当前mid不可能是最终答案, 因为超过了限制
        // 所以必须要将 s == mid 这种情况划给右边, 使区间划分为 [l, mid - 1] 与 [mid, r]
        
        
        // 此时, 返回条件可以是 s >= m, 也可以是 s < m
        return s >= m;
    };

    long long l = 0, r = 1e14;
    while(l < r) {
        long long mid = l + (r - l + 1 >> 1);
        if(check(mid)) {
            l = mid;    // 选择了 s >= m, 那么check为true时, 答案应该在右边这个区间
                        // 但在计算mid时, 若没有 +1, 代表向下取整, 那么计算出来的mid就会落在左区间
                        // 此时再将mid赋值给l就会造成无限循环(因为l本身就在左区间, 你将mid赋值给它, 还在左区间)
        }
        else {
            r = mid - 1;
        }
    }

    if(r == 1e14) {
        cout << "infinite\n";
    }
    else {
        cout << l << "\n";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值