洛谷刷题C++语言 | P1182 数列分段
文章标签:
c++刷题软件
学习C++从娃娃抓起!记录下洛谷C++学习和备考过程中的题目,记录每一个瞬间。
附上汇总贴:洛谷刷题C++语言 | 汇总_热爱编程的通信人的博客-CSDN博客
【题目描述】
对于给定的一个长度为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,含义如题目所述。
【输出】
一个正整数,即每段和最大值最小为多少。
【输入样例】
5 3
4 2 4 5 1
【输出样例】
6
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, m, a[100005], l=0, r=0;
int main()
{
cin >> n >> m;
for (int i=1; i<=n; i++) {
cin >> a[i];
if (l<a[i]) l = a[i];
r += a[i];
}
// cout << "l r " << l << " " << r << endl;
while (l<=r) {
int mid = l + (r-l)/2;
// cout << "mid " << mid << endl;
int count = 1, tmp=0; // 初始分段至少1段
for (int i=1; i<=n; i++) {
if (a[i]+tmp<=mid) tmp += a[i]; // 至少是1段,所以要加上a[i]
else {
count++;
tmp = a[i];
}
}
if (count<=m) r= mid-1;
else l = mid+1;
}
cout << l << endl;
return 0;
}
【运行结果】
5 3
4 2 4 5 1
6