1. 程式人生 > 實用技巧 >從 Java 原始碼閱讀中汲取設計思想及示例解讀(上)

從 Java 原始碼閱讀中汲取設計思想及示例解讀(上)

題目描述

  • 在某個海邊小國,大多數居民都是漁民,這個國家的所有城鎮都沿直線分佈在海邊。漁民們捕獲大量的海魚,但就象世界上大多數的漁民一樣,他們並不喜歡吃魚,所以他們決定從鄰國收養一些貧困家庭的小孩,讓他們來幫著吃魚,國家規定每個城鎮收養的貧困兒童數量必須相等。
  • 一條又長又直的公路貫穿整個海岸將所有的城鎮連線了起來,所以每個城鎮(除去第一個和最後一個)都直接和相鄰的兩個城鎮相連線。一個小孩一年要吃掉一噸魚,每個城鎮捕獲的魚既可以在本地吃也可以運往其它城市吃,在運輸過程中,每公里要上交一噸魚作為過路費。
  • 已知每個城鎮一年的捕魚產量,並假設運輸方案是最佳的,計算最多能收奍多少個貧困兒童。

輸入格式

  • 第一行包含一個整數 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;
}