P1182 数列分段 Section II 题解

题目传送门

一、为什么可以使用二分,怎么想到的?

每段和的最大值最小。,提示的很明显,什么最大值最小,最小值最大等等,均可以视为二分答案题。为啥呢?因为二分的本质是区间逼近,这样才能求出极值,不用二分你说用啥?

二、二分查找的是什么?

本题查找的肯定是每段和的最大值,逼近的是让它最小。

三、左右边界值是多少?

每段和的极限情况:(1)一个数字一段;(2)所有数字在一段里。
每个数字独自一段的话,最大值就是max(a[i])
所有数字在一段的话,最大值就是sum(a[i])

四、是向左逼近,还是向右逼近?

求最大值的最小。即向左逼近

五、check函数的实现

按东北话来讲,就是:逮着一个往死了加,直到冒了就再开一个房间~
最终是否符合是题意要求就是: cnt<=m

六、C++代码

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int a[N];
int n, m;

//检查函数
bool check(int mid) {
    int cnt = 1; //最小一个区间
    int sum = 0; //区间和
    for (int i = 1; i <= n; i++) {
        //区间和计算
        sum += a[i];
        //如果超过了mid值
        if (sum > mid) {
            cnt++; //需要下一个段了~
            sum = a[i];
        }
    }
    //是否符合题意的要求,在m个区间段范围内?
    return cnt <= m;
}

int l, r;

int main() {
    cin >> n >> m;
    //输入
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        l = max(l, a[i]);
        r += a[i];
    }

    while (l < r) {
        int mid = l + r >> 1;//mid的定义:每段和
        if (check(mid)) r = mid;//向左逼近
        else l = mid + 1;
    }
    //输出大吉
    cout << l << endl;
    return 0;
}

posted @   糖豆爸爸  阅读(127)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2018-07-26 OpenLDAP在win2008上安装配置
2017-07-26 开放API端口SIGN算法详细设计
2013-07-26 MariaDB5.5.32 绿色版下载安装一条龙
Live2D
点击右上角即可分享
微信分享提示