【二分】复制书稿

复制书稿

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值