1 solutions

  • 2
    @ 2025-8-8 20:58:49

    /* 题目:给定一个长度为 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;
    }
    
    • 1

    Information

    ID
    2
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    3
    Tags
    # Submissions
    26
    Accepted
    6
    Uploaded By