G - 土耳其冰淇凌 Gym - 101194D(二分答案 + 贪心检验)

熊猫先生非常喜欢冰淇淋,尤其是冰淇淋塔。一个冰淇淋塔由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个球最多能形成的多少个 “球塔”?

  • 分析:然我们球最多数量,我们可以用二分去假设某个答案,假设完这个答案之后我们要看看,这个答案能 被n个小球组成,这个时候我们就需要写个 Judge函数来检验了

    1. 对于这个检验主要是用 “贪心” 的思想,首先我们假设 能形成 m个“球塔”,那么 对于这个m个球塔最上边的球,一定是前m小的球,这样我们 在剩下的小球继续 以贪心的思想继续放置就行了

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

const int Len = 3e5 + 10;
int n, m;
ll ar[Len];
ll br[Len];

bool Judge(int mid)
{
    for(int i = 1; i <= mid; i ++)
        br[i] = ar[i];

    for(int i = mid + 1, j = mid + 1; i <= mid * m; i ++)
    {
        while(ar[j] < br[i-mid] * 2 && j <= n)
            j ++;
        if(j == n + 1) return false;
        br[i] = ar[j ++];
    }
    return true;
}

int main()
{
    /* freopen("A.txt","r",stdin); */
    int t, Case = 1;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i ++)
            scanf("%lld", &ar[i]);
        sort(ar + 1, ar + 1 + n);
        int l = 0, r = n/m;
        int ans;
        while(l <= r)
        {
            int mid = (l + r) >> 1;
            if(Judge(mid))
                l = mid + 1, ans = mid;
            else
                r = mid - 1;
        }
        printf("Case #%d: %d\n",Case ++, ans);
    }


    return 0;
}

总结

  1. 对于这种让求最大组成数量的题,一定要想一下“能否用二分答案
  2. 还是对贪心思想掌握的不行,在做这一题的时候就完全没想到这个贪心思路
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值