2016ChinaFinal(ShangHai) D

题意:给你N个数,代表冰淇淋球直径,要求每个冰淇凌由K个球组成,并且下层球的大小至少是上层球的2倍。问最多能做多少个冰淇凌。

分析:二分+贪心。我们先假设一个答案x为最多能做冰淇凌的个数,然后再验证它能不能做出来。二分这个x,就行了。验证的话,贪心的选取,也就是一层一层的做。第一层肯定选直径最小的x个球。第二层,那么就依次选刚好是上层2倍的球。

代码:

 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
",test,lo);
50     }
51     return 0;
52 }
View Code
原文地址:https://www.cnblogs.com/sun-yinkai/p/7754828.html