袋鼠认妈妈(加强版)
原题链接:http://codeforces.com/problemset/problem/372/A
不过这道题目是一道变形题,在原题的基础上面做了修改,所以这里的标程不能过CF原题。
【题目描述】
有 n 只袋鼠(题目假设他们都是母的),你需要给他们组建成家庭。
对于第 i 只袋鼠来说,它的大小用一个数字 Si 来表示。
如果第 i 只袋鼠的大小 Si 达到了第 j 只袋鼠的大小 Sj 的两倍(即满足Si>=2*Sj),那么第 i 只袋鼠可以做第 j 只袋鼠的妈妈。
注意这道题目(加强版)和前面那道题目的区别就是:在这道题目里面,当了妈妈的袋鼠还是可以认妈妈的,但是一只袋鼠最多只能有一个女儿。
也就是说:一只袋鼠最多有一个女儿,它的女儿(乳沟有的话)也最多有一个女儿。
一只袋鼠和她的女儿和女儿的女儿和女儿的女儿的女儿和…………组成一个家庭。
为了让袋鼠尽可能地不孤单,你希望尽可能多的凑成家庭。在这种情况下,家庭的数量是最少的。
请输出进行组合后能够组成的最少的家庭数量。
举个例子:如果有4只袋鼠,它们的大小分别是 1, 2, 5, 12。那么你可以将 1 的妈妈设成 2,将 2 的妈妈设成 5,将 5 的妈妈设成 12 。
所以在这种情况下,最少的家庭数量是 1 。
【输入格式】
输入的第一行包含一个一个整数 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; }
原文地址:https://www.cnblogs.com/ocac/p/11156526.html