OCAC暑期比赛第三场 I题 袋鼠认妈妈 题解

Posted ocac

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OCAC暑期比赛第三场 I题 袋鼠认妈妈 题解相关的知识,希望对你有一定的参考价值。

袋鼠认妈妈
原题链接:http://codeforces.com/problemset/problem/372/A
【题目描述】
有 n 只袋鼠(题目假设他们都是母的),你需要给他们组建成家庭。
对于第 i 只袋鼠来说,它的大小用一个数字 Si 来表示。
如果第 i 只袋鼠的大小 Si 达到了第 j 只袋鼠的大小 Sj 的两倍(即满足Si>=2*Sj),那么第 i 只袋鼠可以做第 j 只袋鼠的妈妈。
并且如果第 i 只袋鼠已经做了另一只袋鼠的妈妈的话,那么她就不能再认妈妈了。
一对母女袋鼠 或者 单独的一只袋鼠 都算一个家庭。
为了让袋鼠尽可能地不孤单,你希望尽可能多的凑成家庭。在这种情况下,家庭的数量是最少的。
请输出进行组合后能够组成的最少的家庭数量。
举个例子:如果有4只松鼠,它们的大小分别是 1, 6, 7, 8。那么你可以选择大小为 1 的松鼠和其他大小的任意一只松鼠组成一个家庭,
所以在这种情况下,最少的家庭数量是 3 。
【输入格式】
输入的第一行包含一个一个整数 n (1<=n<=5*10^5)。
接下来 n 行每行包含一个整数,第 i+1 行对应第 i 只松鼠的大小 Si 。(1<=Si<=10^5)
【输出格式】
输出一个整数,表示组合后能够凑成的最少的家庭数。
【样例输入1】
8
2
5
7
6
9
8
4
2
【样例输出1】
5
【样例输入2】
8
9
1
6
2
6
5
8
3
【样例输出2】
5
【问题分析】
这道题目涉及的算法:二分。
首先我们要来分析一下,如果这道题目告诉你一个 num ,问你组成 num 个家庭的方案能够实现,你能不能做?
我们可以写一个函数 bool check(int num) ,
然后我们来分析这个 check 函数,
组件 num 个家庭,那也就是说有 k = n- num 个袋鼠要放到另一个袋鼠的口袋里(认妈妈)。
那么我们首先需要对袋鼠的大小 (我们这里用数组 a[] 表示) 从小到大排个序,
然后我们从 0 到 k-1 遍历 i,a[i]放到a[i+num]里,如果不能放,则 check 返回 false。
如果都能放,则 check 返回 true 。
然后我们看一下答案的范围是在 (n+1)/2 到 n 之间的满足 check 条件的 最小的数。
所以我们设 L = (n+1)/2 , R = n 。在这个范围内进行二分,即可找到答案。
实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 500050;
int n, a[maxn];
 
bool check(int num) 
    int k = n - num;
    for (int i = 0; i < k; i ++) 
        if (a[i] * 2 > a[i+num]) return false;
    
    return true;

 
int solve() 
    int L = (n+1)/2, R = n, res;
    while (L <= R) 
        int mid = (L + R) / 2;
        if (check(mid)) 
            res = mid;
            R = mid - 1;
         else 
            L = mid + 1;
        
    
    return res;

 
int main() 
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> a[i];
    sort(a, a+n);
    cout << solve() << endl;
    return 0;

 

以上是关于OCAC暑期比赛第三场 I题 袋鼠认妈妈 题解的主要内容,如果未能解决你的问题,请参考以下文章

OCAC暑期比赛第三场 F题 魔法力量 题解

OCAC暑期比赛第三场 G题 汉堡汪 题解

OCAC暑期比赛第三场 H题 01字符串 题解

OCAC暑期比赛第三场 E题 线上的点 题解

OCAC暑期比赛第一场 I题 大小写转换密码锁 题解

OCAC暑期比赛第二场 B题 日常浇花 题解