(超详细)POJ3104 Drying(让我痛不欲生的二分)

Description

It is very hard to wash and especially to dry clothes in winter. But Jane is a very smart girl. She is not afraid of this boring process. Jane has decided to use a radiator to make drying faster. But the radiator is small, so it can hold only one thing at a time.

Jane wants to perform drying in the minimal possible time. She asked you to write a program that will calculate the minimal time for a given set of clothes.

There are n clothes Jane has just washed. Each of them took ai water during washing. Every minute the amount of water contained in each thing decreases by one (of course, only if the thing is not completely dry yet). When amount of water contained becomes zero the cloth becomes dry and is ready to be packed.

Every minute Jane can select one thing to dry on the radiator. The radiator is very hot, so the amount of water in this thing decreases by k this minute (but not less than zero — if the thing contains less than k water, the resulting amount of water will be zero).

The task is to minimize the total time of drying by means of using the radiator effectively. The drying process ends when all the clothes are dry.

Input

The first line contains a single integer n (1 ≤ n ≤ 100 000). The second line contains ai separated by spaces (1 ≤ ai ≤ 109). The third line contains k (1 ≤ k ≤ 109).

Output

Output a single integer — the minimal possible number of minutes required to dry all clothes.

Sample Input

sample input #1
3
2 3 9
5

sample input #2
3
2 3 6
5

Sample Output

sample output #1
3

sample output #2
2

 题意:n件衣服要烘干,第i件衣服的水分为a[i],烘干机每次只能放进一件衣服,每分钟能烘干的水分为k,同时每分钟没有放在洗衣机的衣服的水分会自然蒸发1,求最短需要多少时间把衣服全部烘干。

思路:拿到这个题,想到用二分来做不难,难得是如何写判断的函数。。。(吐血。。)

首先理顺一下题目,我们二分的是题目所求也就是最少用的时间,写到二分里就是mid。那么我们如何判断mid是否符合要求来缩小范围呢?

判断函数的写法是这个题的关键,

先来想想简单的部分:如果所有的a[i]都小于mid,那么肯定是可行的,都不需要用洗衣机,放在那风干时间也不会超过mid。

 但是如果有的a[i]大于mid呢?我们知道如果这些衣服都不放洗衣机的话,也会自动减少水分,这是自然发生的,不管你有没有用洗衣机,然后设给i件衣服用了t时间的洗衣机,那么mid时间后,自然风干后剩下的水就是 a[i]-(mid-t) (因为在洗衣机里不能风干),

这些水没有别的办法只能用洗衣机了,所以,我们只需要看这这些a[i]>mid的衣服用的洗衣机时间的总和有没有超过mid,如果超过了,肯定是不满足的。

剩下的问题就是如何得到这个t,很简单,风干后剩下的水就得用洗衣机来除掉,又知道用了t时间的洗衣机。我们可以推导出一个式子:k*t=a[i]-(mid-t)  我们需要看的就是这些t的总和于mid的比较关系

移项之后可以得到:t=(a[i]-mid)/(k-1) 

有两个需要注意的地方:

1、t的结果需要向上取整,因为你的余数再用一次洗衣机无非就是多1个时间,但是如果你风干的话,就是用至少1时间,向上取整的方法咱们后面再说

2、这个式子的分母是k-1,当k==1的时候要单独拿出来讨论,不然会RE,也很简单,其实k==1的时候就相当于风干呗,直接输出最大的含水量就可以了

 

看代码吧

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n;
long long k;
long long a[100055];
int judge(int x)
{
	long long sum=0;
	long long maxx=0;
	for(int i=0;i<n;i++)
	{
		if(a[i]>x) //自然风干时间不够,需要使用洗衣机 
		{
			//sum+=ceil((a[i]-x)/(k-1)); //这里用ceil函数会WA
			sum+=(a[i]-x+k-2)/(k-1); //分子后面+((分母)-1)这种取整方法我也是第一次见
		}
		if(sum>x) return 0;
		
	}
	return 1;
}
void solve()
{
	int l=1,r=a[n-1];
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(judge(mid)) r=mid-1;
		else l=mid+1;
	}
	cout<<l<<endl;  //这里是我的习惯问题,while里边的判断条件习惯写成L<=r
}                   //那么l=mid+1,r=mid-1,同时最终输出哪个也得好好想想
                    //当l==r时如果不成立肯定要取L+1,这里正好不成立后l会加1,所以输出l
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&a[i]);
	}
	scanf("%lld",&k);
	sort(a,a+n);
	if(k==1)
	{
		printf("%lld\n",a[n-1]);
		return 0;
	}
	solve();
	return 0;
}

 

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值