牛客多校第五场-平均绩点(二分)

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

Kanade selected n courses in the university. The academic credit of the i-th course is s[i] and the score of the i-th course is c[i].

At the university where she attended, the final score of her is 

Now she can delete at most k courses and she want to know what the highest final score that can get.

输入描述:

The first line has two positive integers n,k

The second line has n positive integers s[i]

The third line has n positive integers c[i]

输出描述:

Output the highest final score, your answer is correct if and only if the absolute error with the standard answer is no more than 10-5

示例1

输入

复制

3 1
1 2 3
3 2 1

输出

复制

2.33333333333

说明

Delete the third course and the final score is 

备注:

1≤ n≤ 10^5

0≤ k < n

1≤ s[i],c[i] ≤ 10^3

 

题意:给定 n 门课以及它们的学分和绩点,定义总绩点是所有课的加权平均数,给定一个数 k,
你可以删除最多 k 门课,求你的总绩点最大能到多少

思路:居然是个二分,死活没想到

D为所求答案,二分答案

//牛客第五次多校A题自写 AC
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, k;
int s[N], c[N], id[N];//id为编号
double ans;//二分的答案
inline bool cmp(const int &a, const int &b) {//根据题解排序
	return s[a] * (c[a] - ans) > s[b] * (c[b] - ans);
}
bool check(double ans) {
	::ans = ans;//局部变量赋值给全局变量
	nth_element(id + 1, id + n - k, id + n + 1, cmp);//把第n-k大的数放到按从大到小排序的第n-k位置上,左边的比它大,右边的比他小,复杂度O(N)
	ans = 0;
	for (int i = 1; i <= n - k ; ++i)ans += s[id[i]] * (c[id[i]] - ::ans);//前面n-k个全要
	//大于0的才要
	for (int i = n - k + 1; i <= n; ++i)if (s[id[i]] * (c[id[i]] - ::ans) > 0)ans += s[id[i]] * (c[id[i]] - ::ans);
	return ans > 0;
}
int main() {
	cin >> n >> k;
	for (int i = 1; i <= n; ++i)scanf("%d", &s[i]);
	for (int i = 1; i <= n; ++i)scanf("%d", &c[i]);
	for (int i = 1; i <= n; ++i)id[i] = i;
	double l = 0, r = 1e3;
	for (int i = 0; i < 50; ++i) {//多次二分
		double mid = (l + r) / 2;
		if (check(mid))l = mid;
		else r = mid;
	}
	printf("%.6lf\n", ans);//输出结果,误差小于10^-5
	return 0;
}

总结:  有时候题目给出误差小于多少的时候可以优先考虑二分,这个数据也比较小,答案在10^3内,二分次数不多

::x代表全局变量x

nth(a,a+k-1,a+n);把大小顺序为第k小的数放在第k个位置上,左边的比它小,右边的比它大,无序,复杂度O(n)

从大到小排序就是把第k大的数放在第k位置上

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值