【ccf】202012-2 期末预测之最佳阈值【枚举、前缀和、二分/双指针/循环判断条件】

原题链接

❄️ | 题目描述

给出n个标准,以及对应的n个结果。结果为1代表通过考试,结果为0代表不通过考试

要求在n个标准中选出一个作为阈值。使得预测准确的数量达到最大

预测准确是:当标准 < 阈值,结果为0;当标准 > 阈值,结果为1

如果有预测准确的数量一样的阈值,选择最大的。

✨ | 实现思路

首先应该将n组数据排序

在这里插入图片描述

加入选择3作为阈值,那么预测准确的次数就是:

3右边(包括3)结果为1的数 + 3左边(不包括3)结果为0的数【这里可以用前缀和快速统计】

从大到小枚举,最后选择出答案。

当然枚举是需要注意:有可能枚举的标准是相等的,那么一定要将指针移动到最左边【第一个大于下一个不同标准的位置】。因为预测的能通过的标准是 ≥ Yi

当然也可以通过二分查找确定下标位置

💓 | 具体代码

  • 二分

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    typedef pair<int, int> PII;
    #define x first
    #define y second
    
    const int N = 100010;
    
    int n;
    int a[N];
    PII res[N];
    int cnt[N];
    
    int main()
    {
        cin >> n;
        for (int i = 1; i <= n; i ++)
        {
            int y, w; cin >> y >> w;
            res[i] = {y, w};
            a[i] = y;
        }
        
        sort(res + 1, res + 1 + n);
        sort(a + 1, a + 1 + n);
        
        for (int i = 1; i <= n; i ++)
            cnt[i] = res[i].y + cnt[i - 1];
            
        int ans = 0, mmax = -1;     // 求最大值时注意初始化
        for (int i = n; i >= 1; i --)
        {
            int pos = lower_bound(a + 1, a + 1 + n, a[i]) - a - 1;  // 找到小于当前阈值的第一个(最大的)数
            // cout << pos << ' ';
            int num = cnt[n] - cnt[pos] + pos - cnt[pos];   // 预测正确的个数
            if (num > mmax)
            {
                mmax = num;
                ans = a[i];
            }
        }
        cout << ans << endl;
    }
    
  • 继续循环判断条件

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef pair<int, int> PII;
    #define x first
    #define y second
    
    const int N = 100010;
    int n;
    int s[N];
    PII w[N];
    
    int main()
    {
        cin >> n;
        for (int i = 1; i <= n; i ++)
        {
            int a, res;
            cin >> a >> res;
            w[i] = {a, res};
        }
        w[0] = {-1, 0};
        
        sort (w + 1, w + 1 + n);
        
        
        s[n + 1] = 0;
        for (int i = n; i >= 0; i --)
        {
            s[i] = s[i + 1] + w[i].y;
        }
        /*
            s[i]: y >= yi时,成绩是1的数量
        */
        
        int ans = 0;
        int num = 0;
        for (int i = n; i >= 0; i --)
        {
            if (w[i].x == w[i - 1].x) continue;     // 这里可以用二分找到大于 w[i].x 的最小的数
            if (s[i] + i - (s[1] - s[i]) > num)     // 预测成功的数量 = 1~i-1中为0的数量 + i~n中为1的数量
            {
                num = s[i] + i - (s[1] - s[i]);
                ans = w[i].x;
            }
        }
        
        cout << ans << endl;
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值