渔民的烦恼

渔民的烦恼( 二分\(\star \))

  • 时限:\(1s\) 内存:\(256M\)

Descrption

  • 在某个海边小国,大多数居民都是渔民,这个国家的所有城镇都沿直线分布在海边。渔民们捕获大量的海鱼,但就象世界上大多数的渔民一样,他们并不喜欢吃鱼,所以他们决定从邻国收养一些贫困家庭的小孩,让他们来帮着吃鱼,国家规定每个城镇收养的贫困儿童数量必须相等。
  • 一条又长又直的公路贯穿整个海岸将所有的城镇连接了起来,所以每个城镇(除去第一个和最后一个)都直接和相邻的两个城镇相连接。一个小孩一年要吃掉一吨鱼,每个城镇捕获的鱼既可以在本地吃也可以运往其它城市吃,在运输过程中,每公里要上交一吨鱼作为过路费。
  • 已知每个城镇一年的捕鱼产量,并假设运输方案是最佳的,计算最多能收奍多少个贫困儿童。

Input

  • 第一行包含一个整数 \(N\),其中 \(1≤N≤100,000\),表示城镇总数。
  • 接下来的 \(N\) 行每行包含两个整数 \(A\)\(B\),其中 \(1≤A≤1,000,000,000,0≤B≤1,000,000,000\),分别表示城镇的位置(坐标)和该城镇的捕鱼产量,所有城镇按其位置从小到大排序给出,注意问题一定存在正整数解。

Output

  • 输出文件仅一行,包含一个整数表示每个城镇最多能够收养的贫困儿童数量。

Sample Input

4
20 300
40 400
340 700
360 600

Sample Output

415

Hint

  • 来源:

分析

  • 明显的二分答案。

Code

#include <bits/stdc++.h>
const int maxn=1e5+5;
typedef long long LL;
int n,posi[maxn];
LL fish[maxn];
bool Check(int x){
    LL Flow=0;//记录货物流动情况
    for(int i=1;i<n;++i){
        LL y=fish[i]+Flow;//到第i村庄时有多少鱼
        if(y<x)
            Flow=y-x-(posi[i+1]-posi[i]);//向i+1借鱼
        else{
            Flow=y-x-(posi[i+1]-posi[i]);//可以向i+1送鱼
            if(Flow<0)
                Flow=0;//剩下的鱼不够路费的就不送了
        }
    }
    return fish[n]+Flow>=x;//最后一个村庄是否养活x个孩子
}
int Binary(int l,int r){
    while(l<r){
        int mid=(l+r+1)>>1;//+1避免死循环
        if(Check(mid))l=mid;
        else r=mid-1;
    }
    return l;
}
void Solve(){
    scanf("%d",&n);
    LL Max=0;
    for(int i=1;i<=n;++i){
        scanf("%d%lld",&posi[i],&fish[i]);
        Max=std::max(Max,fish[i]);
    }
    printf("%d\n",Binary(0,Max));
}
int main(){
    Solve();
    return 0;
}
posted @ 2020-07-18 11:02  ♞老姚♘  阅读(195)  评论(0编辑  收藏  举报