https://www.nowcoder.com/acm/contest/143/A
时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K,其他语言524288KSpecial Judge, 64bit IO Format: %lld
题目描述
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≤ 105
0≤ k < n
1≤ s[i],c[i] ≤ 103
题目大意:
给定 n( 1 <=n <=10^5 ) 门课以及它们的学分和绩点,定义总绩点是所有课的加权平均数,给定一个数 k, 你可以删除最多 k 门课,求你的总绩点最大能到多少
想法:
想到了要把最后K个差的课程删掉。想了很久该怎么给课排序。然而WA了很多发。余老板说这个是最大化平均值,然后二分平均值就AC了。
思路:
参照标准题解:
考虑分数规划 二分答案,假设当前二分了一个值D,我们要判断是否存在一个方案使得总绩点>=D
化简过程:
(
每个都si,ci已知,二分枚举D,满足第三式子,然后按 取前K小的课删掉就可以(因为课越少越好)。
余老板:
观察式子,把s[i]c[i]当作物品的价值,s[i]当作物品的重量,那么题目就变成了最大化平均值问题。二分枚举平均值x,判断能否选到(价值-重量*x)>=0的前n-k个物品。
AC代码:
余老板:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 1e5 + 5;
typedef long long LL;
LL n, k, s[MAXN], c[MAXN];
double y[MAXN];
bool check(double x) {
for (int i = 0; i < n; ++i) y[i] = s[i] * c[i] - x * s[i];
sort(y, y + n);
double sum = 0;
for (int i = k; i < n; ++i) sum += y[i];
return sum >= 0;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/lance/CLionProjects/code/nower_coder/Multi_University_Training_Contest/2018/five/input.txt", "r+",
stdin);
// freopen("data.out", "w+", stdout);
#endif
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k;
for (int i = 0; i < n; ++i) cin >> s[i];
for (int i = 0; i < n; ++i) cin >> c[i];
double start = 0, end = INF, mid;
for (int i = 0; i < 100; ++i) {
mid = (start + end) / 2;
if (check(mid)) start = mid;
else end = mid;
}
cout.setf(ios::fixed);
cout << setprecision(6) << end << endl;
return 0;
}