题意:
把一个包含N个正整数的序列划分成M个连续的子序列,设第i个序列的总和为Si,求使得Si的最大值最小的划分序列
明显的最大值最小化问题。。。
设Si的最大值最小为x,所有数之和为M,二分[0,M]即可求出X的值
代码:
#include <cstdio>
#include <cstring>
#define LL long long
LL a[1111];
int main()
{
int t; scanf("%d",&t);
while(t--)
{
int n, m;
scanf("%d %d",&n,&m);
LL sum= 0;
for(int i= 1; i<= n; i++)
{
scanf("%lld",&a[i]);
sum+= a[i];
}
LL L= 0, R= sum;
while(L< R)
{
// printf("%lld %lld\n",L,R);
LL mid= (L + R)/ 2;
int cnt= 1; //划分次数
LL s= 0; //当前和
for(int i= 1; i<= n; i++)
{
if(a[i]> mid)// 当序列有一个数大于mid,表示mid不可行
{
cnt= m+1;
break;
}
s+= a[i];
if(s> mid)
{
cnt++;
s= a[i];
}
}
if(cnt<= m)
R= mid;
else
L= mid + 1;
}
int b[555];
memset(b, 0, sizeof(b));
LL xx= 0;
for(int i= n; i>= 1; i--)
{
xx+= a[i];
if(xx> L )
{
b[i]= 1;
xx= a[i];
m--;
}
}
m--;
//printf("%d\n",m);
for(int i= 1; m&& i<= n; i++)
if(b[i]== 0)
{
b[i]= 1;
m--;
}
printf("%lld",a[1]);
if(b[1])
printf(" /");
for(int i= 2; i<= n; i++)
{
printf(" %lld",a[i]);
if(b[i])
printf(" /");
}
printf("\n");
}
return 0;
}