CCF202012-2(前缀和+二分)

期末预测之最佳阈值

题目

n个学生,每个学生有一个阈值和一个结果,结果有0,1两种选择,现在可选择阈值进行判断大于阈值取1,小于取0,问预测结果正确的次数最多的阈值是谁,如果预测次数相同,输出最大的阈值。

思路

  • 结果和数据输入无关可排序,且如果有序,那么显然该阈值左侧预测结果为0,右侧为1,因此可以在排序后预处理出0,和1出现的次数,之后次数就是0,1个数和。
  • 考虑到有阈值相同的情况,此时我们要的结果仅应得到第一个和他相同的阈值,可以用二分查找得到第一个相同的元素

AC代码

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define debug(x) cout << "> " << x << endl;
#define endl '\n'
//#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 10 + 1e5, mod = 1e9 + 7;
int n;
PII a[N];
int cnt0[N], cnt1[N];

int binary_s(int i)
{
    int x = a[i].first;
    int l = 0, r = n + 1;
    while (l + 1 != r)
    {
        int mid = l + r >> 1;
        if (a[mid].first < x)  l = mid;
        else  r = mid;
    }
    return r;
}

void solve()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &a[i].first, &a[i].second);
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n; i++)
    {
        if (a[i].second == 1)
            cnt1[i] = cnt1[i - 1] + 1, cnt0[i] = cnt0[i - 1];
        else cnt0[i] = cnt0[i - 1] + 1, cnt1[i] = cnt1[i - 1];
    }
    int mx = -inf, res = 0;
    for (int i = 1; i <= n; i++)
    {
        int id = binary_s(i);
        int tot = cnt0[id - 1] + (cnt1[n] - cnt1[id - 1]);
        if (tot > mx)
        {
            mx = tot;
            res = a[id].first;
        }
        else if (tot == mx)
            res = max(res, a[id].first);
    }
    printf("%d", res);
}
signed main()
{

    solve();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值