渔民的烦恼

题目描述

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

输入格式

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

输出格式

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

样例

样例输入

4
20 300
40 400
340 700
360 600

样例输出

415

题解

  • 明显的二分板子,细节很多,需要注意!!!

code

/*
4
20 300
40 400
340 700
360 600
*/
/*
415
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
long long pos[maxn],v[maxn];
long long n;
bool check(long long sum){
	long long fish=0;
	for(int i=1;i<n;++i){
		long long cnt=v[i] + fish;
		if(cnt < sum)
			fish=cnt-sum-(pos[i+1]-pos[i]);
		else {
			fish=cnt-sum-(pos[i+1]-pos[i]);
			if(fish < 0)fish=0;
		}
	}
	if(v[n]+fish>=sum)return true;
	return false;
}
int main(){
	cin>>n;
	long long Max=0;
	for(int i=1;i<=n;++i){
		cin>>pos[i]>>v[i];
		Max=max(Max,v[i]);
	}
	long long l=0;
	long long r=Max;
	while(l <= r){
		int mid=(l+r)>>1;
		if(r-l == 1){
			if(check(r))l=r;
			cout<<l;
			return 0;
		}
		if(check(mid))l=mid;
		else r=mid;
	}
	cout<<l;
	return 0;
}
原文地址:https://www.cnblogs.com/hellohhy/p/13337467.html