熊猫先生非常喜欢冰淇淋,尤其是冰淇淋塔。一个冰淇淋塔由K个冰淇淋球堆叠成一个塔。为了使塔稳定,下面的冰淇淋球至少要有它上面的两倍大。换句话说,如果冰淇淋球从上到下的尺寸是A0, A1, A2,···,AK 1,那么A0×2 ≤ A1, A1 × 2 ≤ A2,等等。
有一天,熊猫先生在街上走着,发现一家卖冰淇淋球的商店。冰淇淋球共有N个,大小分别为B0、B1、B2、··、BN−1。潘达先生想知道这些球最多能做出的冰淇淋塔数量。
Input
输入的第一行给出了测试用例的数量,接下来是T , T组测试用例。每个测试用例都以一个由2个整数组成的行开始,N是商店中冰淇淋球的数量,K是形成一个冰淇淋塔所需的冰淇淋球的数量。下一行包含N个整数,表示商店中各个冰淇淋球的大小。
Output
对于每个测试用例,输出一行包含“Case #x: y”,其中x是测试用例号(从1开始),y是冰淇淋塔的最大数量。
Limits
• 1 ≤ T ≤ 100.
• 1 ≤ N ≤ 3 × 105.
• 1 ≤ K ≤ 64.
• 1 ≤ Bi ≤ 1018.
Sample Input
3
4 2
1 2 3 4
6 3
1 1 2 2 4 4
6 3
1 1 2 2 3 4
Sample Output
Case #1: 2
Case #2: 2
Case #3: 1
题意:给你n个冰淇淋球,然后告诉你做一个冰淇淋需要k个冰淇淋球,要求下面的冰淇淋球的质量至少是上面冰激凌球质量的两倍,问你最多能做几个冰淇淋。
思路:这道题的话,题里告诉我们有n个冰淇淋球,然后每做一个冰淇凌需要k个冰淇凌球,所以最多可以做n/k个。然后我们有了区间,用二分的方法,设l=0,r=n/k,在这个区间里查找最大值。然后我们知道了用二分来做之后,我们应该检验一下查找的值,我们每做一个冰淇凌球,肯定会把最小的那一个冰淇凌球放在最上面,然后找它的下一层。所以假设我们可以做x个冰淇凌球,我们将最小的放在最上面,然后从第二个开始遍历一遍,找一下是否符合条件,然后检验一下即可。
AC代码:
#include <bits/stdc++.h>
typedef long long ll;
const int maxx=300010;
const int inf=0x3f3f3f3f;
using namespace std;
ll a[maxx],b[maxx];
int n,k;
int ef(int mid)
{
int x=1;
for(int i=1; i<=mid; i++)
b[i]=a[x++];
for(int i=2; i<=k; i++)
{
for(int j=1; j<=mid; j++)
{
while(a[x]<b[j]*2 && x<=n)
x++;
if(x>n)
return 0;
b[j]=a[x++];
}
}
return 1;
}
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
cas++;
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++)
scanf("%lld",&a[i]);
sort(a+1,a+n+1);
int l=0,r=n/k;
int ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(ef(mid))
{
l=mid+1;
ans=mid;
}
else
r=mid-1;
}
printf("Case #%d: %d\n",cas,ans);
}
return 0;
}