期 末 预 测 之 最 佳 阈 值

360 篇文章 3 订阅
9 篇文章 0 订阅

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

因为安全指数越高表明小菜同学挂科的可能性越低,所以当 时,顿顿会预测小菜这学期很安全、不会挂科;反之若 ,顿顿就会劝诫小菜:“你期末要挂科了,勿谓言之不预也。”
题目链接
终于理解了这道前缀和的题目啦!想不到一年后的我再次进化,此题直接拿下!

具体的思路就是运用前缀和的思想,大大降低了时间复杂度,如果用暴力法,时间是 n2,是必然会超时的,所以我们使用巧妙的思路。

首先定义结构体,存储每个位对应的两个数,然后需要先将 结构体按照阀值从小到大的循序进行排序,这样子在定义最佳阀值的时候,比大的都在右侧,比小的都在左侧,计算前缀和,由于结果不是 0 就是 1,所以,1 的个数就是前缀和的个数,0 的个数就是总的个数减去 1 的个数。

然后开始进行求解,这里使用一个集合 set 来去除重复的元素,至于为什么要去重,分析在下面。

开始求解,由于右边的数字都比 阀值大,所以结果是 1 的还是预测正确,只需要计算 sum[n] - sum[i - 1] 即可
左边的阀值都小,所以只需要计算 0 的个数,只需要让总个数 i - 1 减去 1 的个数 sum[i - 1] 即可

每次如果遇到大的就更新,由于 阀值从小到大,所以最后的最佳阀值就是最大的。

至于为什么要去重,我有一些理解,如果不去重会有错误的情况。
举个例子;

0 1
1 0
1 1
3 1

此例子中,阀值 1 出现了两次,由于 大于等于 1 的result 结果都是 1才正确,所以此时大于等于 1 的结果,是 2,但是如果不去重,下一个阀值还是 1,此时小于 1 应该是 0 才对,但是我们计算了 i - 1 - sum[i - 1] 是将该索引前面所有的 0 都加上了,此时的 前面的 1 不满足题意,所以就错误了
在画个图分析一下吧
在这里插入图片描述
在这里插入图片描述

至于为什么要去重,我这里再分析一下:
比如题目中的例子

在这里插入图片描述

#include<iostream>
#include<string>
#include<algorithm>
#include<bits/stdc++.h>
#include<stack>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#include<cctype>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<cstring>
using namespace std;
const int N = 100010;
struct Node {
	int y;
	int result;
};
bool cmp(Node a, Node b) {
	return a.y < b.y;
}
Node a[N];
set<int> st;
int sum[N];
int main() {
	int n;
	int max_num = -1;
	int res = 0;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].y >> a[i].result;
	}
	sort(a + 1, a + n + 1, cmp);
	for (int i = 1; i <= n; i++) {
		sum[i] = sum[i - 1] + a[i].result;
	}
	for (int i = 1; i <= n; i++) {
		int dns = a[i].y;
		if (st.count(dns)) {
			continue;
		}
		st.insert(dns);
		int right = sum[n] - sum[i - 1];
		int left = i - 1 - sum[i - 1];
		int sum = right + left;
		if (sum >= max_num) {
			max_num = sum;
			res = dns;
		}
	}
	cout << res;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_努力努力再努力_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值