A. 【例题1】数列分段
题目
题解
假设最优解为
s
u
m
sum
sum,那么
s
u
m
sum
sum越大,分成的段数就越小;
s
u
m
sum
sum越小,分成的段数就越大。
所以答案符合单调性,可以用二分判定:
若最优解为
s
u
m
sum
sum分成的段数小于
m
m
m,则说明
s
u
m
sum
sum太大,需往左区间查找。反之亦然。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
int l,r,n,m,a[100001];
void in()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
{
cin>>a[i];
l=max(a[i],l);//二分区间中最小为数列中最大的数
r+=a[i];//二分区间中最大为数列中的数之和
}
}
bool check(int mid)
{
int c=1,s=0;//c为段数,s为每段之和
for(int i=1; i<=n; i++)
{
if(s+a[i]<=mid) s+=a[i];
else
{
s=a[i];
c++;
}
}
if(c<=m) return 1;
else return 0;
}
int main()
{
in();
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;//分成的段数小于 m,则说明 mid太大,需往左区间查找
else l=mid+1;//反之亦然
}
cout<<l;
}