问题描述
我的某室友学过素描,墙上有n张他的作品。这些作品都是宽度为1,高度不定的矩形,从左到右排成一排,且底边在同一水平线上。
宿舍评比就要来了,为了及格,我们决定买不多于m块的矩形木板,把这些作品和谐掉。要求木板也从左到右排成一排,且底边与作品的底边在同一水平线上。
在能够把所有作品和谐掉的前提下,我们希望最大的那块木板的面积最小,问最大木板的面积。
输入格式
第一行两个数n和m,表示作品数和木板数;
第二行n个数Hi,表示从左到右第i个作品的高度。
输出格式
一行一个数ans,表示答案。
样例输入
5 2
4 2 3 5 4
样例输出
12
数据规模和约定
对于30%的数据:1<=n,m<=10;
对于100%的数据:1<=n,m<=100000,1<=Hi<=10000。
#include <bits/stdc++.h>
using namespace std;
long long l;
long long r;
long long n, m;
long long *a;
long long check(long long mid)
{
long long wrap = 0;
// long long sum = 0;
for (long long i = 0; i < n;)
{
wrap += 1; // 包裹数加一
long long length = 1;
long long ma = a[i];
while (1)
{
long long maxTemp = ma;
ma = max(ma, a[i + length]);
if (ma * (length + 1) <= mid && i + length < n) // 不超过
{
// 还要判断是否超索引了
length++;
}
else
{
i += length;
break;
}
}
// cout << i << " " << a[i] << " " << sum << " " << mid << endl;
}
if (wrap <= m)
return 1;
else
return 0;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
a = new long long[n];
long long ma = -1;
for (long long i = 0; i < n; i++)
{
cin >> a[i];
ma = max(ma, a[i]);
}
long long sum = ma * n;
l = ma;
r = sum;
long long ans = 0;
while (l <= r) // 二分
{
long long mid = (l + r) / 2;
// cout << l << " " << r << " " << mid << endl;
if (check(mid)) // 检查是否满足条件
{
ans = mid;
r = mid - 1; // 缩小范围继续二分
}
else
l = mid + 1; // 继续向右半段二分
}
cout << ans;
delete a;
return 0;
}