【COCI 2011/2012 CONTEST #5-2】砍樹
Time Limit:10000MS Memory Limit:32000K
Total Submit:49 Accepted:26
Case Time Limit:1000MS
Description
N棵樹,每棵都有一個整數高度。有一個木頭的總需要量M。
現在確定一個最大的統一的砍樹高度H,如果某棵樹的高度大於H,則高出的部分被砍下。使得所有被砍下的木材長度之和達到M(允許稍超過M)。
例如,有4棵樹,高度分別是20 15 10 17, 需要的木材長度為 7,砍樹高度為15時,第1棵樹被砍下5,第4棵樹被砍下2,得到的總長度為7。如果砍樹高度為16時,第1棵樹被砍下4,第4棵樹被砍下1,則得到的木材數量為5。
Input
第1行:2個整數N和M,N表示樹木的數量(1 ≤ N ≤ 1 000 000),M表示需要的木材總長度(1 ≤ M ≤ 2 000 000 000)。
第2行: N個整數表示每棵樹的高度,值均不超過1 000 000 000。所有木材高度之和大於M,因此必然有解。
Output
第1行:1個整數,表示砍樹的最高高度。
Sample Input
5 20
4 42 40 26 46
Sample Output
36
Source
Croatian Open Competition in Informatics 2011/2012
解題思路:
這道題目就是直接把最低的樹和最高的樹選出來,然后構成一個[l,r]的區間,在這個區間上進行二分,
找到一個h,使得a[i]>=k,且滿足sum>=m的最大的h,既然要求最大的,那么我們最后輸出r就
可以了。
代碼:

1 # include<cstdio> 2 # include<iostream> 3 # include<algorithm> 4 5 using namespace std; 6 7 # define MAX 1000000+4 8 9 int a[MAX]; 10 int n,m; 11 int l,r; 12 int check ( int h ) 13 { 14 int sum = 0; 15 for ( int i = 0;i < n;i++ ) 16 { 17 if ( a[i] > h ) 18 { 19 sum+=(a[i]-h); 20 } 21 if ( sum >= m ) 22 { 23 return 1; 24 } 25 } 26 return 0; 27 } 28 29 int main(void) 30 { 31 scanf("%d%d",&n,&m); 32 for ( int i = 0;i < n;i++ ) 33 { 34 scanf("%d",&a[i]); 35 l = min(l,a[i]); 36 r = max(r,a[i]); 37 } 38 while ( l <= r ) 39 { 40 int mid = (l+r)>>1; 41 if ( check(mid) ) 42 { 43 l = mid+1; 44 } 45 else 46 { 47 r = mid-1; 48 } 49 } 50 printf("%d\n",r); 51 return 0; 52 }