1 solutions
-
2
/* 题目:给定一个长度为 N 的正整数序列,将序列分成 M段,使得每段的和的最大值最小。 暴力做法:枚举可能出现的段,再去找最小值。但是 N和 M(1 ≤M ≤N ≤10^6)所以说肯定会超时(10的12次方)。 再看题目 想让每段的和的‘最大值最小’,说明可以用到二分答案。 那设什么呢?常见来讲二分答案大多数情况就是求什么二分什么,所以我们就二分每段的和的最大值。 还有我们初始的左边界与右边界:初始左边界就是最小值 ,最小的情况就是一个一段则左边界就是最大的数-1;右边界就是最大值,则全部数一段,则为所有数的和。 */
#include<bits/stdc++.h> using namespace std; int n,m,a[1000005],l=1,r,ans,sum,s,x,cnt; int main(){ cin>>n>>m;//输入 for(int i=1;i<=n;i++){ cin>>a[i]; l=max(l,a[i]-1);//左边界(最大的数-1) r+=a[i];//右边界(所有数的和) } a[n+1]=0; while(r-l!=1){//开始二分 int mid=(l+r)/2;//答案 for(int i=1;i<=n;i++){ sum+=a[i];//某段的和 if(sum<mid&&sum+a[i+1]>mid){ s++;//表示分一段 sum=0;//一定要清零 } if(sum==mid){//特判如果相等 s++; sum=0; } } if(sum!=0)s++;//特判如果sum里还有值,就说明要再分一段 if(s<=m){//如果满足条件 ans=mid;//更新答案 r=mid;//往更小的数那边看,寻找更小值 } else{ l=mid;//说明mid小了,往右(更大的)边去找 } s=0; sum=0;//清零 } cout<<ans;//输出最终答案 return 0; }
Information
- ID
- 2
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 3
- Tags
- # Submissions
- 26
- Accepted
- 6
- Uploaded By