复制书稿
Time Limit:1000MS Memory Limit:65536K
Total Submit:59 Accepted:27
Description
有M本书(编号为1,2,…,M),每本书都有一个页数(分别是P1,P2,…,PM)。想将每本都复制一份。将这M本书分给K个抄写员(1<=K<=M<=500),每本书只能分配给一个抄写员进行复制。每个抄写员至少被分配到一本书,而且被分配到的书必须是连续顺序的。复制工作是同时开始进行的,并且每个抄写员复制一页书的速度都是一样的。所以,复制完所有书稿所需时间取决于分配得到最多工作的那个抄写员的复制时间。试找一个最优分配方案,使分配给每一个抄写员的页数的最大值尽可能小。
Input
第一行两个整数M、K;(K<=M<=100)
第二行M个整数,第i个整数表示第i本书的页数。
Output
共K行,每行两个正整数,第i行表示第i个人抄写的书的起始编号和终止编号。K行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。
Sample Input
9 3
1 2 3 4 5 6 7 8 9
Sample Output
1 5
6 7
8 9
标准的二分,能抄就尽量抄,后面的人一定能尽量少抄。
最后求出了答案之后,从最后往前贪心一次就行了。
#include <cstdio>
long m,k;
long mid;
long page[1000];
long ans2[1000];
long ans = 0x7f7f7f7f;
void work()
{
long people = k;
long sum = 0;
for (long i=m;i>0;i--)
{
if (sum+page[i]<ans+1)
sum += page[i];
else
{
ans2[people] = i+1;
people--;
sum = page[i];
}
}
ans2[1] = 1;
ans2[k+1] = m+1;
for (long i=1;i<k+1;i++)
printf("%ld %ld\n",ans2[i],ans2[i+1]-1);
}
bool can()
{
long people = 1;
long sum = 0;
for (long i=1;i<m+1;i++)
{
if (page[i] > mid)
return false;
if (sum+page[i]<mid+1)
{
sum += page[i];
}
else
{
sum = page[i];
people++;
if (people>k)
return false;
}
}
return true;
}
int main()
{
freopen("copy.in","r",stdin);
freopen("copy.out","w",stdout);
scanf("%ld%ld",&m,&k);
long l = 0;
long r = 0;
for (long i=1;i<m+1;i++)
{
scanf("%ld",page+i);
r += page[i];
}
while (l <= r)
{
mid = (l+r)>>1;
if (can())
{
if (mid < ans)
ans = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
work();
return 0;
}