codeforces-372A

本文详细介绍了如何通过优化二分查找算法解决特定袋鼠装袋问题,包括理解题意、算法设计、代码实现及优化过程。重点解决了数据范围内的边界值处理,确保算法在复杂数据输入下仍能正确运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:
There are n kangaroos with pockets. Each kangaroo has a size (integer number). A kangaroo can go into another kangaroo’s pocket if and only if the size of kangaroo who hold the kangaroo is at least twice as large as the size of kangaroo who is held.

Each kangaroo can hold at most one kangaroo, and the kangaroo who is held by another kangaroo cannot hold any kangaroos.

The kangaroo who is held by another kangaroo cannot be visible from outside. Please, find a plan of holding kangaroos with the minimal number of kangaroos who is visible.

Input
The first line contains a single integer — n(1 ≤ n ≤ 5·105). Each of the next n lines contains an integer si — the size of the i-th kangaroo (1 ≤ si ≤ 105).

Output
Output a single integer — the optimal number of visible kangaroos.

Sample Input
Input
8
2
5
7
6
9
8
4
2
Output
5
Input
8
9
1
6
2
6
5
8
3
Output
5

题意:
有n只袋鼠,小袋鼠能装进大袋鼠里面,但大袋鼠的体型要大于或等于小袋鼠的两倍,小袋鼠被装后不能看见外面,求至少能有多少只袋鼠看得见(设为K)。

理解:
二分做法:
n-k只袋鼠看不见,则外形最小的n-k只袋鼠会被外形最大的n-k只大袋鼠装在口袋里。
贪心:
对n只袋鼠,平均分成两部分,则最优情况是前一半的袋鼠会被后一半的袋鼠装在口袋里。对每一步,最优做法是最后一只袋鼠装住中间的袋鼠,依此类推,即为最优

下面贴代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
int a[500100];
using namespace std;

int select(int key, int n)
{
    int temp = n-1;
    int flag;
    for(int i=key; i>=0; i--)
    {
        if( 2*a[i] <= a[temp])
        {
            temp--;
            flag = 1;
        }
        else
        {
            flag=-1;
            break;
        }
    }
    return flag;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        for(int i=0; i<n; i++) scanf("%d",&a[i]);
        sort(a, a+n);
        //for(int i=0; i<n; i++) printf("%d ",a[i]);

        int low = 0;
        int high = (n+1)/2;
        while(low <= high)                     //YRNL....error
        {
            int mid = (low+high) / 2;
            if ( select(mid-1, n)== -1)      //fail,reduce
                high = mid -1;
            else low = mid + 1;
        }
        if(2*high > n) printf("%d\n",n-high+1);  //yue jie le
        else printf("%d\n",n-high);
    }
    return 0;
}

写题目时莫名卡数据了,看了数据,发现有一种情况二分越界了。原因是我的二分写法是搜到正确答案后继续后退了一位,正常情况会判断后再前进得到正确答案。但是卡的数据类似于1,2,3),4,6,6,10
二分得到正确的被装的袋鼠的最大值应该是3,组合如下(3,10) (2,6) (1,6) ( 4 )
但是二分越界后(1,2,3,4),6,6,10,组合变为:
(4,10) (3,6) (2,6) (1,4)
同样满足二分的条件。。。。。且temp也越过了中界。。。。

因为这个二分写法必定会越界再返回,改其他的值都会导致新的错误,但考虑上面这种情况只需要在输出时判断,并且分别输出就够了。。。。因为能越过正确值且没有返回,那则说明是中间的袋鼠没有被装,即减一即为正确答案

个人小结:
看数据过题实在是不好。。。。为了过数据而改代码,而不是一开始整体把握思路

PS:
代码还有些地方没想清楚,为什么会出错,可能是和我自己的二分写法有关,暂时记下来,等想明白了再改。。。。

发了博客后马上反应过来。。。。为什么要让二分搜索到不正确的答案呢。。。
处理一下边界值,即当n为奇数时的情况,让他查找不到错误值(最中间的值)。。。归根结底是因为考虑low 和high的值的时候出错了

贴修改后的代码

#include <stdio.h>
#include <string.h>
#include <algorithm>
int a[500100];
using namespace std;

int select(int key, int n)
{
    int temp = n-1;
    int flag;
    for(int i=key; i>=0; i--)
    {
        if( 2*a[i] <= a[temp])
        {
            temp--;
            flag = 1;
        }
        else
        {
            flag=-1;
            break;
        }
    }
    return flag;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        for(int i=0; i<n; i++) scanf("%d",&a[i]);
        sort(a, a+n);
        //for(int i=0; i<n; i++) printf("%d ",a[i]);
        int m = (n+1)/2;
        if(n%2!=0) m--;
        int low = 0;
        int high = m;
        while(low <= high)                   
        {
            int mid = (low+high) / 2;
            if ( select(mid-1, n)== -1)      
                high = mid -1;
            else low = mid + 1;
        }
        printf("%d\n",n-high);
    }
    return 0;
}
### 关于 Codeforces Problem 1802A 目前提供的引用内容并未涉及 Codeforces 编号为 1802A 的题目详情或解决方案[^1]。然而,基于常见的竞赛编程问题模式以及可能的解决方法,可以推测该类题目通常围绕算法设计、数据结构应用或者特定技巧展开。 如果假设此题属于典型的算法挑战之一,则可以从以下几个方面入手分析: #### 可能的方向一:字符串处理 许多入门级到中级难度的问题会考察字符串操作能力。例如判断子串是否存在、统计字符频率或是执行某种转换逻辑等。以下是 Python 中实现的一个简单例子用于演示如何高效地比较两个字符串是否相匹配: ```python def are_strings_equal(s1, s2): if len(s1) != len(s2): return False for i in range(len(s1)): if s1[i] != s2[i]: return False return True ``` #### 方向二:数组与列表的操作 另一常见主题是对整数序列进行各种形式上的变换或者是查询最值等问题。下面给出一段 C++ 程序片段来展示快速寻找最大元素位置的方法: ```cpp #include <bits/stdc++.h> using namespace std; int main(){ int n; cin >> n; vector<int> a(n); for(auto &x : a){ cin>>x; } auto max_it = max_element(a.begin(),a.end()); cout << distance(a.begin(),max_it)+1; // 输出索引加一作为答案 } ``` 由于具体描述缺失,在这里仅提供通用框架供参考。对于确切解答还需要访问实际页面获取更多信息后再做进一步探讨[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值