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

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

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

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

题目描述
具体来说,顿顿评估了 位同学上学期的安全指数,其中第 ()位同学的安全指数为
,是一个
范围内的整数;同时,该同学上学期的挂科情况记作
,其中 表示挂科、 表示未挂科。
相应地,顿顿用 表示根据阈值 将安全指数 转化为的具体预测结果。
如果

相同,则说明阈值为 时顿顿对第 位同学是否挂科预测正确;不同则说明预测错误。

最后,顿顿设计了如下公式来计算最佳阈值 :
该公式亦可等价地表述为如下规则:
最佳阈值仅在 中选取,即与某位同学的安全指数相同;

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

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

输入格式
从标准输入读入数据。
输入的第一行包含一个正整数 。

接下来输入 行,其中第 ()行包括用空格分隔的两个整数
和 ,含义如上文所述。

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

样例1输入

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

样例1输出

3

Data
样例1解释
按照规则一,最佳阈值的选取范围为 。

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

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

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

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

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

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

依规则三,

样例2输入

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

Data
样例2输出

100000000

思路:
一、很明显普通的遍历会超时;这种题限制时间一般有两种解决方案:

1、在输入数据时,就对需要的数据进行记录。

2、对整体数据进行打表操作,此题便用到了打表。

我的代码:

#include<cstdio>
#include<set>
#include<vector>
#include<algorithm> 
#include<unordered_map>
using namespace std;
struct Node
{
	int a,b;//a为每个同学的阈值,b为是否挂科;
}node;
vector<Node> v;
bool cmp (const Node &n1,const Node &n2)//对每个同学阈值从小到大排序
{
	if (n1.a != n2.a) return n1.a < n2.a;
	else return n1.b < n2.b;
}
int main()
{
	int n,p = 0;//p记录多少个未挂科人数
	scanf("%d",&n);
	set<int> s;//记录阈值,排除重复的
	for (int i = 0 ;i < n ;i++)
	{
		scanf("%d%d",&node.a,&node.b);
		v.push_back(node);
		if (node.b == 1) p++;
		s.insert(node.a);
	}
	sort(v.begin(),v.end(),cmp);
	unordered_map<int,int> mp,mp1;//mp1记录每个阈值之前有多少个人挂科的,mp1记录每个阈值之后有多少个未挂科的
	int temp1 = 0,temp2 = 0;//temp1是之前挂科人数,temp2是之后未挂科人数
	for (int i = 0 ;i < v.size() ;i++)
	{
		if (mp.find(v[i].a) == mp.end())
			mp[v[i].a] = temp1;
		if (mp1.find(v[i].a) == mp1.end())	
			mp1[v[i].a] = p - temp2;//跟据总的未挂科人数减阈值之前未挂科的人数得阈值值后未挂科的人数
		if (v[i].b == 0) temp1++;	
		else temp2++;		
	}			
	int maxa = 0 ,maxcnt = 0;//maxa为最大阈值,maxcnt最大预测正确数
	for (auto it = s.begin() ;it != s.end() ;it++)
	{
		if (mp[*it] + mp1[*it] >= maxcnt)//之前挂科的加之后未挂科的人数是否大于最大正确数
		{
			maxa = *it;
			maxcnt = mp[*it] + mp1[*it];
		}
	}
	printf("%d",maxa);
	return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

情书、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值