洛谷题单指南-二分查找与二分答案-P1182 数列分段 Section II

原题链接:https://www.luogu.com.cn/problem/P1182

题意解读:每段和的最大值越小,则分段数就越多,因此可以通过给定每段和的最大值,将分段数划分为两类:<=M,>M,对每段和的最大值进行二分即可。

解题思路:

二分的判定条件为,给定每段和的最大值,计算分段数,计算逻辑如下:

依次遍历每一个数,求当前数到开始数的区间和,

如果区间和大于每段和的最大值,则区间数+1,且当前数作为下一个区间的开始数

最终统计得到区间数,如果区间数<=M,说明符合条件,每段和的最大值可以往更小的进行探索,否则往更大的探索

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;

int a[N], n, m, ans;
long long s[N];

bool check(int x)
{
    int i = 1, last = 1, cnt = 1;
    while(i <= n)
    {
        if(s[i] - s[last - 1] > x)
        {
            last = i;
            cnt++;
        }
        i++;
    }
    return cnt <= m; //分段小于等于m,可以试探分段更多,分段越多,即最大分段和更小
}

int main()
{
    cin >> n >> m;
    int maxx = 0;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        s[i] = s[i - 1] + a[i]; //s是前缀和数组
        maxx = max(maxx, a[i]); //记录最大值
    }

    int l = maxx, r = 1e9; //左边界至少是其中最大的数,即如果每个数一个分段,这时最大的分段和最小,为数列的最大数
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(check(mid)) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    cout << ans;

    return 0;
}

 

posted @   五月江城  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示