時間限制: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位置上