2016ChinaFinal(ShangHai) D - Ice Cream Tower
题意:给你N个数,代表冰淇淋球直径,要求每个冰淇凌由K个球组成,并且下层球的大小至少是上层球的2倍。问最多能做多少个冰淇凌。
分析:二分+贪心。我们先假设一个答案x为最多能做冰淇凌的个数,然后再验证它能不能做出来。二分这个x,就行了。验证的话,贪心的选取,也就是一层一层的做。第一层肯定选直径最小的x个球。第二层,那么就依次选刚好是上层2倍的球。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int MAXN=3e5+7; 6 long long a[MAXN]; 7 long long up[MAXN]; 8 int N,K; 9 bool check(int x) 10 { 11 int i=0; 12 for(;i<x;++i) 13 up[i]=a[i]; 14 for(int k=1;k<K;++k) 15 { 16 for(int j=0;j<x;++j) 17 { 18 while(a[i]/2<up[j]) 19 { 20 ++i; 21 if(i>=N) 22 { 23 return false; 24 } 25 } 26 up[j]=a[i]; 27 ++i; 28 } 29 } 30 return true; 31 } 32 int main() { 33 int T;scanf("%d",&T); 34 for(int test=1;test<=T;++test) 35 { 36 scanf("%d%d",&N,&K); 37 memset(a,0,sizeof(a)); 38 memset(up,0,sizeof(up)); 39 for(int i=0;i<N;++i) 40 scanf("%lld",&a[i]); 41 sort(a,a+N); 42 int lo=0,hi=N+1; 43 while(hi-lo>1) 44 { 45 int m=(hi+lo)/2; 46 if(check(m))lo=m; 47 else hi=m; 48 } 49 printf("Case #%d: %d\n",test,lo); 50 } 51 return 0; 52 }