Problem D. Ice Cream Tower (The 2016 ACM-ICPC Asia China-Final Contest)(二分)

Input file: Standard Input
Output file: Standard Ouptut
Time limit: 6 seconds

Mr. Panda likes ice cream very much especially the ice cream tower. An ice cream tower consists
of K ice cream balls stacking up as a tower. In order to make the tower stable, the lower ice cream
ball should be at least twice as large as the ball right above it. In other words, if the sizes of the
ice cream balls from top to bottom are A0, A1, A2, · · · , AK−1, then A0 × 2 ≤ A1, A1 × 2 ≤ A2,
etc.
One day Mr. Panda was walking along the street and found a shop selling ice cream balls. There
are N ice cream balls on sell and the sizes are B0, B1, B2, · · · , BN−1. Mr. Panda was wondering
the maximal number of ice cream towers could be made by these balls.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test
case starts with a line consisting of 2 integers, N the number of ice cream balls in shop and K
the number of balls needed to form an ice cream tower. The next line consists of N integers
representing the size of ice cream balls in shop.
Output
For each test case, output one line containing “Case #x: y”, where x is the test case number
(starting from 1) and y is the maximal number of ice cream towers could be made.
Limits
• 1 ≤ T ≤ 100.
• 1 ≤ N ≤ 3 × 10^5
.
• 1 ≤ K ≤ 64.
• 1 ≤ Bi ≤ 10^18

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层,即一个塔至少由k个冰淇淋组成,问最多可以堆成多少个塔。

思路:显然,塔的数量具有单调性,所以我们可以对答案进行二分。check也十分简单。假设当前能堆成x座塔,那么每个塔的第一个球的体积肯定是越小越好,所以我们先将球的体积进行排序,然后按顺序放置在x座塔上,铺下一层的时候,依旧按顺序来放,只不过需要比较体积是否是上一层的两倍,不是的话接着按顺序选下一个球比较。最后看是否能达到k层。

代码如下

#include   
#include   
#include  
#include 
#include    
#define ll long long

using namespace std; 
ll H[300005];
int N,K;
ll cheng[300005];


int solve(int num)
{
    int f=1;
    for(int i=1;i<=num;i++)
    cheng[i]=H[f++];

    f--;
    int x=1;
    if(x==K)
    return 1;

    while(1)
    {
        for(int i=1;i<=num;i++)
        {
            if(f+1>N)
            return 0;

            else
            f++;
            while(1)
            {
                if(H[f]>=cheng[i]*2)
                {
                    cheng[i]=H[f];
                    break;
                }
                if(f+1>N)
                return 0;
                else 
                f++;
            }
        }
        x++;
        if(x==K)
        return 1;
    }
}
int main() 
{ 
    int T;
    scanf("%d",&T);
    for(int Cas=1;Cas<=T;Cas++)
    {
        scanf("%d%d",&N,&K);

        for(int i=1;i<=N;i++)
        scanf("%lld",&H[i]);

        sort(H+1,H+N+1);

        int l=0,r=N/K+1;
        while(r-l>1)
        {
            int mid=(l+r)/2;
            if(solve(mid))
            {
                l=mid;
            }
            else 
            r=mid;
        }
        printf("Case #%d: %d\n",Cas,l);
    }
    return 0; 
}

你可能感兴趣的:(二分+三分+分治)