【CSP认证】2020-12-2 期末预测之最佳阈值

参考文章
https://blog.csdn.net/SUN__CGJ/article/details/111224076

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

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

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

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

最佳阈值仅在 𝑦𝑖 中选取,即与某位同学的安全指数相同;
按照该阈值对这 𝑚 位同学上学期的挂科情况进行预测,预测正确的次数最多(即准确率最高);
多个阈值均可以达到最高准确率时,选取其中最大的。

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

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

样例1输入
6
0 0
1 0
1 1
3 1
5 1
7 1

样例1输出
3
1

样例2输入
8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0

样例2输出
100000000

题解

  1. 首先看到n为1e5,两层循环肯定是超时的,只能得70分!
  2. 本题正解思路是,对所有输入进行排序,记录比自己小的标签其值且0的个数,比自己大标签且其值的1的个数。实际上是用排序的方式,减少了重复多余的比较(nlogn)

代码实现

#include<iostream>
#include<algorithm> 
using namespace std;

int n;
const int MAX = 2e5+5;

struct node{
	int x,y;
}a[MAX]; 

struct node2{
	int x,l,u,sum;
}tag[MAX];

bool cmp1(node t1,node t2){
	return t1.x<t2.x;
} 

bool cmp2(node2 t1,node2 t2){
	if(t1.sum==t2.sum){
		return t1.x<t2.x;
	}
	return t1.sum<t2.sum;
} 

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].x>>a[i].y;
	}
	
	sort(a+1,a+n+1,cmp1); // 按照第一个数(标签)升序排序 
	
	int k=1;
	tag[k].x = a[1].x;  // 设置第1个标签 
	for(int i=1;i<=n;i++){
		if(tag[k].x==a[i].x){ // 该标签已设置 
			if(a[i].y==1) tag[k].u++; // 该标签为1计数+1 
			else tag[k].l++; // 该标签为0计数+1 
		}
		else{ // 该标签未设置 
			tag[++k].x = a[i].x;
			if(a[i].y==1) tag[k].u++; // 该标签为1计数+1 
			else tag[k].l++; // 该标签为0计数+1 
		}
	} 
	
	int sum=0;
	// 计算该标签下(包含该标签)有多少个0 
	for(int i=1;i<=k;i++){
		sum += tag[i].l;
		tag[i].l = sum; 
	}
	
	sum = 0;
	// 计算该标签下(包含该标签)有多少个1(即求多少个大于等于该标签的数)
	for(int i=k;i>=1;i--){ // 注意1是从大的往小的方向累积 
		sum += tag[i].u;
		tag[i].u = sum;
	}
	
	// 每个的次数=比自己标签小且其值为0的个数+大于等于自己的标签且其值为1的个数 
	for(int i=1;i<=k;i++){
		tag[i].sum = tag[i].u+tag[i-1].l;
	} 
	
	sort(tag+1,tag+k+1,cmp2);
	cout<<tag[k].x<<endl;
	
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值