【CSP】202012-2 期末预测之最佳阈值

2020年 第21次CCF计算机软件能力认证  202012-2 期末预测之最佳阈值

原题链接:期末预测之最佳阈值

时间限制: 1.0 秒

空间限制: 512 MiB

目录

题目背景

题目描述

输入格式

输出格式

样例1输入

样例1输出

样例1解释

样例2输入

样例2输出

子任务

解题思路

AC代码


期末预测之安全指数

题目背景

考虑到安全指数是一个较大范围内的整数、小菜很可能搞不清楚自己是否真的安全,顿顿决定设置一个阈值 𝜃,以便将安全指数 𝑦转化为一个具体的预测结果——“会挂科”或“不会挂科”。

因为安全指数越高表明小菜同学挂科的可能性越低,所以当 𝑦≥𝜃 时,顿顿会预测小菜这学期很安全、不会挂科;反之若 𝑦<𝜃,顿顿就会劝诫小菜:“你期末要挂科了,勿谓言之不预也。”

那么这个阈值该如何设定呢?顿顿准备从过往中寻找答案。

题目描述

具体来说,顿顿评估了 𝑚位同学上学期的安全指数,其中第 𝑖i(1≤𝑖≤𝑚)位同学的安全指数为 𝑦𝑖,是一个 [0,10^8] 范围内的整数;同时,该同学上学期的挂科情况记作 𝑟𝑒𝑠𝑢𝑙𝑡𝑖∈0,1,其中 0 表示挂科、1 表示未挂科。

相应地,顿顿用 predict𝜃(𝑦)表示根据阈值 𝜃将安全指数 𝑦 转化为的具体预测结果。 如果predict𝜃(𝑦𝑗) 与 𝑟𝑒𝑠𝑢𝑙𝑡𝑗相同,则说明阈值为 𝜃时顿顿对第 𝑗位同学是否挂科预测正确;不同则说明预测错误。

predict𝜃(𝑦) = 0 (𝑦<𝜃)   

predictθ​(y) = 1​ (y≥θ​)

最后,顿顿设计了如下公式来计算最佳阈值 𝜃∗ :

𝜃∗=max ⁡argmax∑(predict𝜃(𝑦𝑗)==𝑟𝑒𝑠𝑢𝑙𝑡𝑗)          𝜃∈yi​         j <= 1 <= m

该公式亦可等价地表述为如下规则:

  1. 最佳阈值仅在 𝑦𝑖​ 中选取,即与某位同学的安全指数相同;

  2. 按照该阈值对这 𝑚 位同学上学期的挂科情况进行预测,预测正确的次数最多(即准确率最高);

  3. 多个阈值均可以达到最高准确率时,选取其中最大的。

输入格式

从标准输入读入数据。

输入的第一行包含一个正整数 𝑚。

接下来输入 𝑚 行,其中第 𝑖i(1≤𝑖≤𝑚)行包括用空格分隔的两个整数 𝑦𝑖和 𝑟𝑒𝑠𝑢𝑙𝑡𝑖,含义如上文所述。

输出格式

输出到标准输出。输出一个整数,表示最佳阈值 𝜃∗。

样例1输入

6
0 0
1 0
1 1
3 1
5 1
7 1

样例1输出

3

样例1解释

按照规则一,最佳阈值的选取范围为{ 0,1,3,5,7}。

𝜃=0 时,预测正确次数为 4;

𝜃=1 时,预测正确次数为 5;

𝜃=3 时,预测正确次数为 5;

𝜃=5 时,预测正确次数为 4;

𝜃=7 时,预测正确次数为 3。

阈值选取为 1 或 3 时,预测准确率最高; 所以按照规则二,最佳阈值的选取范围缩小为 {1,3}。

依规则三,𝜃∗=max⁡(1,3)=3。

样例2输入

8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0

样例2输出

100000000

子任务

70%的测试数据保证 𝑚≤200;

全部的测试数据保证 2≤𝑚≤10^5。

解题思路

1.结构体存储数据。

2.要对数据进行排序(从小到大)再处理。

3.找规律(结论):“θ”值为a[i].y时的预测正确次数 = a[i].y前面有多少resullt = 0 + a[i].y当前和后面有多少resullt = 1

4.根据结论,我们需要知道a[i].y前面有多少resullt = 0 以及 a[i].y当前和后面有多少resullt = 1,也就是说要对每个a[i].y前面的result值进行记录,显然用前缀和可求得。

5.求完前缀和后便可计算出“θ”值为a[i].y时的预测正确次数。注意:对于y值相同的数据,我们只处理一次,否则重复进行计算的结果是错误的。

AC代码

#include<bits/stdc++.h>
 
using namespace std;
 
const int N = 1e5 + 10;
 
int m;

struct x{
    int y;
    int result;
    int sum0;   //记录a[1]——a[i] 有多少resullt = 0
    int sum1;   //记录a[1]——a[i] 有多少resullt = 1
    int sum;    //“θ”值为a[i].y时的预测正确次数 = a[i].y前面有多少resullt = 0 + 当前和后面有多少resullt = 1
}a[N];

bool cmp(x a, x b)
{
    //把y按照从小到大顺序排序 y值相同则把result按从小到大排列
    if(a.y != b.y)  return a.y < b.y;
    else return a.result < b.result;
}

int main()
{
    cin >> m;
    
    for(int i = 1; i <= m; i ++)    cin >> a[i].y >> a[i].result;
    
    sort(a, a+m+1, cmp); 
    
    //统计a[1].y 到 a[i].y 的resullt 0 和 1 的数量(实际上就是求前缀和
    for(int i = 1; i <= m; i ++)
    {
        if(a[i].result == 1) a[i].sum1 += a[i-1].sum1 + 1, a[i].sum0 = a[i-1].sum0 ;
        else a[i].sum0 += a[i-1].sum0 + 1, a[i].sum1 = a[i-1].sum1 ;
    }
    
    int ans = 0, max = 0;
    //统计“θ”值为a[i].y时的预测正确次数
    for(int i = 1; i <= m; i ++)
    {
        //注意 遇到y值相同时要特殊处理 即相同的y值只计算一次
        if(a[i].y == a[i-1].y ) a[i].sum = a[i-1].sum;
        else a[i].sum = a[i-1].sum0 + a[m].sum1 - a[i-1].sum1 ;
        
        if(max <= a[i].sum) max = a[i].sum, ans = a[i].y;
    }
    
    cout << ans << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值