渔民的烦恼
题目描述
- 在某个海边小国,大多数居民都是渔民,这个国家的所有城镇都沿直线分布在海边。渔民们捕获大量的海鱼,但就象世界上大多数的渔民一样,他们并不喜欢吃鱼,所以他们决定从邻国收养一些贫困家庭的小孩,让他们来帮着吃鱼,国家规定每个城镇收养的贫困儿童数量必须相等。
- 一条又长又直的公路贯穿整个海岸将所有的城镇连接了起来,所以每个城镇(除去第一个和最后一个)都直接和相邻的两个城镇相连接。一个小孩一年要吃掉一吨鱼,每个城镇捕获的鱼既可以在本地吃也可以运往其它城市吃,在运输过程中,每公里要上交一吨鱼作为过路费。
- 已知每个城镇一年的捕鱼产量,并假设运输方案是最佳的,计算最多能收奍多少个贫困儿童。
输入格式
- 第一行包含一个整数N,其中1<=N<=100,000,表示城镇总数。
- 接下来的N行每行包含两个整数A和B,其中1<=A<=1,000,000,000,0<=B<=1,000,000,000,分别表示城镇的位置(坐标)和该城镇的捕鱼产量,所有城镇按其位置从小到大排序给出,注意问题一定存在正整数解。
输出格式
输出文件仅一行,包含一个整数表示每个城镇最多能够收养的贫困儿童数量。
样例输
4
20 30
40 400
340 700
360 600
样例输出
415
思路:因为A,B范围较大,二分答案


1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=100000+10,inf=0x3f3f3f3f; 5 typedef long long ll; 6 int a[maxn],b[maxn]; 7 int n,mx=0,mn=inf; 8 bool check(int x){ 9 ll follow=0; 10 for(int i=1;i<n;i++){ 11 ll y=b[i]+follow; 12 if(y<x){ 13 follow=y-x+(a[i]-a[i+1]);//向后边借 14 } 15 else{ 16 follow=y-x-(a[i+1]-a[i]);//向后边送 17 if(follow<0) follow=0;//若多出的不够路费,不送 18 } 19 } 20 return b[n]+follow>=x;//判断最后是否符合要求,因为前面操作确保1到n-1符合 21 } 22 void solve(){ 23 int l=mn,r=mx; 24 while(l<r){//不能写l<=r,可能会死循环,若l==4,r==4,mid==4符合,r==4,有=,l一直等于4 25 int mid=(l+r+1)>>1;//+1避免死循环 26 if(check(mid)) l=mid; 27 else r=mid-1; 28 } 29 printf("%d ",l); 30 } 31 int main(){ 32 scanf("%d",&n); 33 for(int i=1;i<=n;i++){ 34 scanf("%d%d",&a[i],&b[i]); 35 mn=min(mn,b[i]); 36 mx=max(mx,b[i]);//求出二分范围 37 } 38 solve(); 39 return 0; 40 }