Ice Cream Tower Gym - 101194D (贪心 + 二分 )

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Let_life_stop/article/details/84944249

题目链接 : https://cn.vjudge.net/problem/Gym-101194D 

题目大意 : 给你n个冰激凌球,让你用这些冰激凌球去垒冰激凌,要求是下面的这一个必须是他上面一个的两倍大,一个冰激凌需要m个冰激凌,问你最多能造几个冰激凌.

具体思路:  贪心 + 二分 ,首先对输入的n个冰激凌球进行排序,从小到大开始,然后对答案进行二分,从当前的开始,找第一个满足的,然后找完一个再继续找下一个,如果当前要检测的答案是k,那么就需要找k层满足情况的.

AC代码:

#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 500000+10;
ll a[maxn],b[maxn];
ll n,m;
ll Max(ll t1,ll t2)
{
    if(t1<t2)return t2;
    return t1;
}
bool judge(ll t)
{
    ll ans=0;
    for(int i=1; i<=t; i++)
    {
        b[i]=a[i];
    }
    int x=1;
    if(x==m)return true;
    int f=t;
    while(1)
    {
        for(int i=1; i<=t; i++)
        {
            if(f>=n)return false;
            f++;
            while(1)
            {
                if(a[f]>=b[i]*2)
                {
                    b[i]=a[f];
                    break;
                }
                if(f+1>n)return false;
                f++;
            }
        }
        x++;
        if(x==m)return true;
    }
}
int main()
{
    ll T;
    scanf("%lld",&T);
    int Case=0;
    while(T--)
    {
        scanf("%lld %lld",&n,&m);
        for(ll i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
        }
        sort(a+1,a+n+1);
        ll l=0,r=n/m;
        ll ans=0;
        while(l <= r )
        {
            int mid = ( l + r ) / 2;
            if(judge(mid))
            {
                ans=Max( ans, mid );
                l = mid + 1 ;
            }
            else  r = mid - 1 ;
        }
        printf("Case #%d: ",++Case);
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Let_life_stop/article/details/84944249