当前位置: 首页 > news >正文

P1182 数列分段 Section II(二分)

题目描述

对于给定的一个长度为 N 的正整数数列 A1∼N​,现要将其分成 M(M≤N)段,并要求每段连续,且每段和的最大值最小。

关于最大值最小:

例如一数列 4 2 4 5 1 要分成 3 段。

将其如下分段:

[4 2][4 5][1]

第一段和为 6,第 2 段和为 9,第 3 段和为 1,和最大值为 9。

将其如下分段:

[4][2 4][5 1]

第一段和为 4,第 2 段和为 6,第 3 段和为 6,和最大值为 6。

并且无论如何分段,最大值不会小于 6。

所以可以得到要将数列 4 2 4 5 1 要分成 3 段,每段和的最大值最小为 6。

输入格式

第 1 行包含两个正整数 N,M。

第 2 行包含 N 个空格隔开的非负整数 Ai​,含义如题目所述。

输出格式

一个正整数,即每段和最大值最小为多少。

#include <iostream>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n, m, a[N];

bool check(int x) {
    int s = 0, num = 0;
    for (int i = 1; i <= n; i++) {
        if (s+a[i]<=x){
        	s+=a[i];
		} else{
			s=a[i];
			num++;
		}
    }
    return num>=m;
}

int main() {
    cin >> n >> m;
    int l = 0, r = 0;
    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) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }
    cout << l;
    return 0;
}

l = max(l, a[i]):l 是数组最大元素(答案下限)。

r += a[i]:r 是数组总和(答案上限)。

二分查找:

  • if (check(mid)):
    • true:mid 太小(份数太多),加大范围(l = mid + 1)。
    • false:mid 太大(份数不够),缩小范围(r = mid - 1)。

check 函数:

检查如果每份和最多是 x,数组会被分成几份,返回份数是否 ≥ m。

  • 从 a[1] 到 a[n] 遍历。
  • 如果 s + a[i] ≤ x,就把 a[i] 加到当前份(s += a[i])。
  • 如果超过 x,就新开一份(s = a[i]),份数加 1(num++)。

相关文章:

  • T113s3远程部署Qt应用(dropbear)
  • 【家政平台开发(18)】缓存机制设计
  • 基于Python网络爬虫的智能音乐可视化系统(源码+lw+部署文档+讲解),源码可白嫖!
  • 【MATLAB例程】交互式多模型(IMM),模型使用:CV,CT左转、CT右转,二维平面,三个模型的IMM,滤波使用EKF,附下载链接
  • 编程题学习
  • SSE Emitter在Spring Boot和Vue中的简单使用
  • 青少年编程与数学 02-016 Python数据结构与算法 01课题、算法
  • 计算机网络 3-1 数据链路层(功能+组帧+差错控制)
  • 请问你怎么看代软件测试的潜力和挑战?
  • Kafka 漏消费和重复消费问题
  • SDL多线程编程
  • Zemax设计实例:AR近眼显示光学系统(60°视场,8K分辨率,超薄波导)
  • 程序化广告行业(62/89):DSP系统的媒体与PDB投放设置探秘
  • 34% 关税冲击下 LabVIEW 开发的变局
  • 哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义免费下载方法
  • 多线程编程中的锁策略
  • java面试
  • 雅思练习总结(十八)
  • Java的SeleniumChromeDriver的常用方法
  • 从 Dense LLM 到 MoE LLM:以 DeepSeek MoE 为例讲解 MoE 的基本原理