Drying (Poj3104,Northeastern Europe 2005, Northern Subregion)

3 篇文章 0 订阅

AC通道:http://poj.org/problem?id=3104


Drying


Description

现在有 n 件衣服,告诉你每一件衣服上水滴的数量。
每一个时间单位中,衣服会被自然风干1滴水滴。

你也可以使用一个烤火炉(只有一个)。
在每一个时间单位中,这个烤火炉能够给一件衣服(只有一件)减少 k 滴水滴。
当你使用烤火炉时,在该时间单位中,该件衣服不会被自然风干。

现在要你合理地使用烤火炉,使所有的衣服都变干的时间最短。
(每一个时间单位中,烤火炉只能烤一件衣服)


Input

第一行包括一个整数 n ,表示衣服的件数。
第二行包括用空格隔开的 n 个整数,表示每件衣服上水滴的数量。
第三行包括一个整数 k ,表示烤火炉的效率,即它每个时间单位能使衣服减少的水滴数。


Output

只有一个整数,表示最短的时间。


Sample Input 1

3
2 3 9
5


Sample Output 1

2


Sample Input 2

3
2 3 6
5


Sample output 2

2


HINT

对于100%的数据, 1n105 ,衣服上的水滴数为不大于 109 的正整数, 1k109


Solution

这道题,第一感觉是贪心。

枚举每个时间,将水滴数最大的衣服使用烤火炉。当最大水滴数为 0 的时候,就输出当前的时间。
很明显会超时:最坏情况下,最大时间将达到 109

所以要二分。
所以我们将最优化问题转化为了一个判定性问题。

设当前要判断的时间为 t ,对于衣服 i,设其水滴数为 si
显然,我们要判断的,就是烤火炉够不够用。

那么,若 sit ,那么这件衣服可以直接忽略掉,因为它不需要使用烤火炉。

si>t ,那么它如果自然风干,那么设它需要使用烤火炉的时间为 t0
那么有 t0k+tt0si t0k1sit t0sit/k1

为了尽可能少地使用烤火炉,则 t0 sit/k1 向上取整的结果。
需要注意的是,若 k=1 ,上面这个表达式就会出现错误,所以要特判。

遍历完所有的衣服,求出所有 t0 (需要使用烤火炉的衣服)之和。
若这个和大于 t ,那么 t 时间内就不可能让所有衣服变干。

算法总复杂度为 O(nlogTmax)

注意需要用 long long


Code

#include <iostream>
#include <cstdio>

using namespace std;

long long n,la,l=1,r,ans;
long long s[100010];

inline long long Max(long long a,long long b){
    return a>b?a:b;
}

bool pan(long long t){
    long long ti=0;
    for(long long i=1;i<=n;i++){
        if(s[i]>t){
            if((s[i]-t)%(la-1))
                ti+=(s[i]-t)/(la-1)+1;
            else ti+=(s[i]-t)/(la-1); 
            if(ti>t)return false;
        }
    }
    return true;
}

int main(){
    scanf("%I64d",&n);
    for(long long i=1;i<=n;i++){
        scanf("%I64d",&s[i]);
        r=Max(r,s[i]);
    }
    scanf("%I64d",&la);
    if(la==1){printf("%I64d\n",r);return 0;}
    ans=r;
    while(l<=r){
        long long mid=(l+r)/2;
        bool flag=pan(mid);
        if(flag){
            if(ans>mid)ans=mid;
            if(r!=mid-1)r=mid-1;
            else break; 
        }
        else{
            if(l!=mid+1)l=mid+1;
            else break; 
        }
    }
    printf("%I64d\n",ans);
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值