渔民的烦恼
渔民的烦恼( 二分\(\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;
}
hzoi