【洛谷P1182】数列分段 Section Ⅱ
数列分段 Section II
题目描述
对于给定的一个长度为 \(N\) 的正整数数列 \(A_{1\sim N}\),现要将其分成 \(M\)(\(M\leq N\))段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 \(4\ 2\ 4\ 5\ 1\) 要分成 \(3\) 段。
将其如下分段:
第一段和为 \(6\),第 \(2\) 段和为 \(9\),第 \(3\) 段和为 \(1\),和最大值为 \(9\)。
将其如下分段:
第一段和为 \(4\),第 \(2\) 段和为 \(6\),第 \(3\) 段和为 \(6\),和最大值为 \(6\)。
并且无论如何分段,最大值不会小于 \(6\)。
所以可以得到要将数列 \(4\ 2\ 4\ 5\ 1\) 要分成 \(3\) 段,每段和的最大值最小为 \(6\)。
输入格式
第 \(1\) 行包含两个正整数 \(N,M\)。
第 \(2\) 行包含 \(N\) 个空格隔开的非负整数 \(A_i\),含义如题目所述。
输出格式
一个正整数,即每段和最大值最小为多少。
样例 #1
样例输入 #1
5 3
4 2 4 5 1
样例输出 #1
6
提示
对于 \(20\%\) 的数据,\(N\leq 10\)。
对于 \(40\%\) 的数据,\(N\leq 1000\)。
对于 \(100\%\) 的数据,\(1\leq N\leq 10^5\),\(M\leq N\),\(A_i < 10^8\), 答案不超过 \(10^9\)。
解法&个人感想
其实这题我觉得没什么要说的 嘿嘿
因为跟前面那题跳石头思路太像了
主要就是要强调一个l,r赋初值的范围
我们都知道平时l一般赋值是1或者0 r我的个人习惯是1e9
但是本题中因为有阴间的hack数据 由题意得知我们此时为了取出最大的一个序列
而每个序列至少含有一个数字 所以l应该取a[i]中最大的那个值
而平时也经常看到r取a[i]之和 这里不加赘述
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m;
int a[100005];
bool check(int x){
int cnt=1,ans=0;
for(int i=1;i<=n;i++){
if(ans+a[i]>x){
ans=0;
cnt++;
}
ans+=a[i];
}
return cnt<=m;
}
int main(){
scanf("%d%d",&n,&m);
int l=0,r=0,mid;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);r+=a[i];l=max(l,a[i]);
}
while(l<=r){
mid=(l+r)/2;
if(check(mid)) r=mid-1;
else l=mid+1;
}
printf("%d",l);
system("pause");
return 0;
}

浙公网安备 33010602011771号