#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
ll t,n,m,l,r,mid;
ll arr[1000],vis[1000];
void Print(int ans)
{
memset(vis,0,sizeof(vis));
ll num=1,s=0;
for(int i=n-1; i>=0; i--)//因为要多解满足前面的小,所以倒过来分组
{
if(s+arr[i]>ans || i+num<m)//如果分好一组,或者剩下个数的加上分好的组数不足m组
{
num++;
s=arr[i];
vis[i]=1;//想到了倒过来分组一开始没想出来怎么处理,看了刘汝佳的代码,用一个vis用来标记‘/’的位置
}
else s+=arr[i];
}
for(int i=0; i<n; i++)
{
if(i!=n-1) printf("%lld ",arr[i]);
else printf("%lld\n",arr[i]);
if(vis[i]) printf("/ ");
}
}
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&n,&m);
ll sum=0;
l=0;
for(ll i=0; i<n; i++)
{
scanf("%lld",&arr[i]);
sum+=arr[i];
l=max(l,arr[i]);
}
r=sum;
while(l<r)//l初始为最大的单个元素,因为顶多也就是每个元素单独成组,r初始为元素和,最少也就是所有元素分一组。
{
mid=(l+r)/2;
ll num=1,s=0;
for(ll i=0; i<n; i++)
{
if(s+arr[i]<=mid)
s+=arr[i];
else
{
num++;
s=arr[i];
}
}
if(num>m) l=mid+1;
else r=mid;//这个地方不用减一
}
Print(l);//l或者r都对,mid不行
}
return 0;
}
这道题不难,但是很久没做二分了,回顾下细节