“最大值最小化”问题,先二分求最大值,再贪心实现按最左边区间最小的格式输出 。
代码如下:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
#ifdef test
freopen("in.txt", "r", stdin);
#endif
int a[505], b[505];
int k, m, num;
scanf("%d", &num);
while(num--)
{
long long left = 0, right = 0, ct, to, mid;
memset(b, 0, sizeof(b));
scanf("%d%d", &m, &k);
for(int i = 0; i < m; i++)
{
scanf("%d", &a[i]);
right += a[i];
}
while(left < right) // 二分求最大值
{
ct = 0, to = 0;
mid = (left + right) / 2;
for(int i = 0; i < m; i++)
{
to += a[i];
if(a[i] > mid) // 当单个元素大于中值时,需增大mid的值
{
ct = k; // 使其跳出
break;
}
if(to >= mid)
{
if(ct >= k)
break;
ct++;
to = a[i];
}
}
if(ct > k - 1)
left = mid + 1;
else
right = mid;
}
for(int cct = 0, tot =0, i = m - 1; i >= 0; i--) // 贪心
{
tot += a[i];
if(a[i] > mid) //二分求最大值时可能有一点小误差,当单个元素略大于最大值时,用此更新最大值
mid = a[i];
if(cct < k - 1 && (tot > mid || i < (k - 1) - cct)) // 区间值大于最大值或是所剩元素与所剩区间数相等时都需划分
{
b[i] = 1;
tot = a[i];
++cct;
}
}
for(int i = 0; i < m; i++)
{
printf("%d%c", a[i], i != m-1 ? ' ' : '\n');
if(b[i])
printf("/ ");
}
}
return 0;
}