洛谷题单指南-二分查找与二分答案-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 @ 2024-03-02 21:25  五月江城  阅读(22)  评论(0编辑  收藏  举报