画匠问题
题目描述
给定一个整型数组arr, 数组中的每个值都为正数,表示完成一幅画作需要的时间,再给定一个整数num,表示画匠的数量,每个画匠只能画连在一起(即数组内连续的一段)的画作。所有画家并行工作,请返回完成所有的画作的最少时间。
[要求]
时间复杂度为 O ( n log S ) O(n \log S) O(nlogS)(其中S表示所有画作所需时间的和)
输入描述:
第一行两个整数N, K表示数组大小,画匠的数量。
接下来一行N个整数表示完成每幅画作所需要的时间。
输出描述:
输出一个整数表示答案
示例1
输入
3 2
3 1 4
输出
4
说明
最好的分配方式为第一个画匠画3和1,所需时间为4,第二个画匠画4,所需时间为4。因为并行工作,所以最少时间为4,如果分配方式为第一个画匠画3,所需时间为3,第二个画匠画1和4,所需的时间为5,那么最少时间为5,显然没有第一种分配方式好,所以返回4
示例2
输入
5 3
1 1 1 4 3
输出
4
说明
最好的分配方式为第一个画匠画前三个1,所需时间为3,第二个画匠画4,所需时间为4,第三个画匠画3,所需时间为3,返回4
示例3
输入
5 2
99 82 44 35 3
输出
164
说明
[99] [82 44 35 3]
备注:
1
⩽
K
⩽
N
⩽
1
0
5
1 \leqslant K \leqslant N \leqslant 10^5
1⩽K⩽N⩽105
∑
i
=
1
n
a
r
r
i
⩽
1
0
18
\sum_{i=1}^n arr_i \leqslant 10^{18}
∑i=1narri⩽1018
题解:
二分时间,以时间为限制,判断完成所有画所需要的工人数目与 K 的大小关系。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100000;
const int INF = 1 << 30;
typedef long long LL;
int n, k;
int a[N];
int check( LL limit ) {
int cnt = 1;
LL sum = 0;
for ( int i = 0; i < n; ++i ) {
if ( a[i] > limit ) return INF;
sum += a[i];
if ( sum > limit ) {
++cnt;
sum = a[i];
}
}
return cnt;
}
int main(void) {
scanf("%d%d", &n, &k);
LL l = 0, r = 0;
for ( int i = 0; i < n; ++i ) {
scanf("%d", a + i);
r += a[i];
l = max( l, (LL)a[i] );
}
while ( l < r ) {
LL mid = l + r >> 1;
if ( check( mid ) > k ) l = mid + 1;
else r = mid;
}
printf("%lld\n", r);
return 0;
}