代码源每日一题div2 分段求和

该博客介绍了如何解决一个数学问题,即如何将一个正整数数列分成最多M段,使得每段连续且每段和的最大值最小。作者通过二分查找和贪心策略实现了一个解决方案,详细阐述了思路和代码实现过程,重点讨论了如何在二分查找中判断条件并进行段的划分。
摘要由CSDN通过智能技术生成

分段求和 - 题目 - Daimayuan Online Judge

题意:

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

思路:

看到最大值最小,就想到二分

我们把每段和最大值二分出来即可

那么怎么check?

在二分里贪心是个非常常见的思路,我们维护双指针l和r,每当超过二分出来的值的时候,r--之后区间[l,r]就是一个段。为什么要快超过二分出来的值的区间作为一个段,因为这样操作过去操作到数列最后,如果发现段的数量>m,就说明我们取段之和最大的情况都不够分段,段之和更小的时候就一定不够分段,所以return false。但是如果段的数量<=m,说明只需要把前面分的段再细分一点就能使得段数等于m,因此这种情况return true

Code:

#include <bits/stdc++.h>
using namespace std;
const int mxn=1e5+10;
#define int long long
int n,m,ans;
int a[mxn],s[mxn];
bool check(int x){
	int l=1,r=1,cnt=0;
	while(1){
		while(s[r]-s[l-1]<=x&&r<=n) r++;
		cnt++;
		if(cnt>m) return false;
		if(r>n) break;
		l=r;
	}
	if(cnt<=n) return true;
	return false;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=s[i-1]+a[i];
	int l=1,r=1e9;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid)){
			ans=mid;
			r=mid-1;
		}else l=mid+1;
	}
	printf("%lld\n",ans);
}

总结:简单二分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值