1. 程式人生 > 實用技巧 >【二分】P1462 通往奧格瑞瑪的道路

【二分】P1462 通往奧格瑞瑪的道路

前置芝士:二分

[P1182]

對於給定的一個長度為N的正整數數列 \(A_{1 \sim N}\),現要將其分成 \(M (M≤N)\)段,並要求每段連續,且每段和的最大值最小。

眼神告訴我,每段和的最大值滿足:

  1.有上下界。
  2.有單調性。

求最值考慮二分。
每段和的最大值上界即為所有數之和,下界為數列元素的最大值。
二分到x後check(x),計算若每段之和不大於x可以分多少段,若大於等於m則向上二分,否則向下二分。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,m,a[maxn];
int l,r,tot,cnt;
bool judge(int x,int a[]){
	for(int i=0;i<n;i++){
		if(tot+a[i]<=x)tot+=a[i];
		else tot=a[i],cnt++;
	}
	return cnt>=m;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
		r+=a[i];
		l=l>a[i]?l:a[i];
	}
	while(l<=r){
		int mid=l+r>>1;
		tot=cnt=0;
		if(judge(mid,a))l=mid+1;
		else r=mid-1;
	}
	printf("%d",l);
	return 0;
}