挺好的一个二分加贪心的题目 。。 思想虽然不是很难,但是 也许还可以。
题意: 题目含义就类似于堆雪人堆蛋糕,,要求下一层至少是上一层的两倍。 给你一个k 表示层数 给你n个 数 表示每一层的大小 问你最多能堆成几个k层的 雪人。
思路: 最少堆成 0个 最多堆成 n/k 个。(二分 n/k ) 如果将最大堆成n个 会超时。 剩下的就是贪心的过程 , 给你一个 mid 你要求的是 是否能够对出 mid 个雪人。
贪心过程 中 一共有mid 个雪人 , 如果贪心到的该层对于一个较小的雪人 都不 适应 那么对于一个较大的雪人肯定也是不适应的,
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N =3e5+5;
long long a[N];
long long rec[N][2];
int n,k;
int jud(int num)
{
int pre=0,now=1;
int p=1;
for(int i=1;i<=num;i++) rec[i][pre]=a[p++];
for(int kk=1;kk<k;kk++)
{
for(int i=1;i<=num;i++)
{
while(a[p]<rec[i][pre]*2) p++;
if(p>n) return 0;
rec[i][now]=a[p++];
}
swap(pre,now);
}
return 1;
}
int main()
{
int cas;
cin>>cas;
int left,right,mid;
int fin;
for(int cc=1;cc<=cas;cc++)
{
//printf("cc: %d \n",cc);
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
if(k>=61)
{
printf("Case #%d: %d\n",cc,0);
continue;
}
left=0; right=n/k;//一个优化 不然会超时。。。
while(left<=right)
{
mid=(left+right)>>1;
//printf("cnt : %d\n",mid);
int f=jud(mid);
//printf("f: %d\n",f);
if(f){
fin =mid;
left=mid+1;
}
else right=mid-1;
}
printf("Case #%d: %d\n",cc,fin);
}
return 0;
}