Gym - 101194 D Ice Cream Tower 二分 + 贪心判断

1.题意:给你n个冰激凌球的体积,告诉你k个球能合成一个冰激凌,合成条件是放在第一个球下面的球体积要大于等于他的两倍。问你最多能合成多少个。

2.分析:

最少能合成0个,最多能合成n/k个。存在单调性上下界,于是我们二分合成数量。

怎么判断mid个能否合成呢?我们知道最上面的球体积越小,可选择的情况越多,合成得最多!所以既然要合成mid个,我们就选前mid个作为mid个冰激凌的顶部,以此类推选下一个底,看看能否合成mid个即可。

3.代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef  long long LL;
const int maxn = 300000 + 100;
LL num[maxn],check[maxn];
int n,k;
bool judge(int u){
    int i;
    for(i = 0;i<u;i++)check[i] = num[i];//前mid个作为顶球
    for(int p = 1;p<k;p++){//每一个要选k个合成
        for(int j = 0;j<u;j++){//进行u次
            if(i>=n)return false;
            int pos = lower_bound(num+i,num+n,check[j]*2) - num;
            if(pos>=n){
                return false;
            }
            check[j] = num[pos];
            i = pos+1;
        }
    }
    return true;
}
int main()
{
    int T;
    scanf("%d",&T);
    int t = 0;
    while(T--){
        t++;
        scanf("%d%d",&n,&k);
        for(int i = 0;i<n;i++){
            scanf("%lld",&num[i]);
        }
        if(k==1){
            printf("Case #%d: %d\n",t,n);
            continue;
        }
        sort(num,num+n);
        int l = 0,r = n/k;
        int ans = 0;
        while(l<=r){//二分
            int mid = (l + r)/2;
            if(judge(mid)){//判断mid个能否合成
                ans = mid;
                l = mid+1;
            }
            else r = mid-1;
        }
        printf("Case #%d: %d\n",t,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40772692/article/details/82965303