洛谷P1182 --数列分段 Section II(二分答案)最大值问题最小化

题目链接

题意:
从n个数中选出连续的m个区间,对于每种选择方案都有一个最大的区间和,求在所有可行方案中最大区间和最小为多少。

题目条件:
对于20%的数据,有N≤10;
对于40%的数据,有N≤1000;
对于100%的数据,有N≤100000,M≤N,A i之和不超过10^9。

分析:
做的时候,最后写代码的时候卡了好久。最后意识到之前的对二分答案的理解有些差错,想法实际和最小值最大化相像,不过本题不需要排序,先直接确定二分边界,最大区间和不小于所有数中最小的数,最大区间和不大于所有数的和,然后check函数,利用贪心思想,选择满足区间和不超过ans的区间,使得得到尽可能少的区间数,如果最后cnt还是>m,说明这种方案不可行,然后应该在左区间二分寻找答案,而while的二分部分又是将最大值最小化的过程,这里提供了两种写法,一开始我以为check返回cnt<=m和cnt>=m都可以,但是实际上cnt=m时,答案应该在左区间,而如果返回cnt>=m时,cnt=m的时候就会在mid~r寻找答案,所以还需注意。然后只要二分写法正确,答案就不会出错。

主要代码

int n,m;
bool check(vector& a,ll ans){
	ll cnt=0,sum=0;
	for(int i=0;im;
}
void solve(){
	vector a(n);
	ll l=0,r=0;
	for(int i=0;i>a[i];
		l=max(l,(ll)a[i]);
		r+=a[i];
	}
	while(l>1;
		if(check(a,mid))
		l=mid+1;
		else
		r=mid;
	}
	cout<>n>>m)
	solve();
	return 0;
}

第二种写法

int n,m;
bool check(vector& a,ll ans){
	ll cnt=0,sum=0;
	for(int i=0;i a(n);
	ll l=0,r=0;
	for(int i=0;i>a[i];
		l=max(l,(ll)a[i]);
		r+=a[i];
	}
	while(l>1;
		if(check(a,mid))
		r=mid;
		else
		l=mid+1;
	}
	cout<>n>>m)
	solve();
	return 0;
}

你可能感兴趣的:(基础算法,二分算法,二分算法,基础算法)