[POJ2976] Dropping Tests
link:http://poj.org/problem?id=2976
description:
There are n courses, \(a_i\)is your grade, while the full marks is \(b_i\). The GPA calculate method is
GPA \(= 100\frac {\sum_{i=1}^n a_i}{\sum_{i=1}^{n}b_i}\)(四舍五入)
Now you have chance to drop some of the courses such that you can get the highest GPA.
solution:
Notice: \(0\) to \(100\) is discrete and so small! So try the solution space is just \(100\)
\(100\sum_{i=1}^{n}a_i-gpa\sum_{i=1}^{n}b_i\geqslant 0\)
\(100\sum_{i=1}^{n}a_i-(gpa+0.5)\sum_{i=1}^nb_i\) vs \(0\)(四舍五入)
Find the highest GPA
My first thought is check from \(100\) down to \(0\)(linear), such that the time complexity is \(O(nk)\)
But the better solution is binary search, \(O(n\log k)\)
code:
#include<cstdio>
#include<algorithm>
typedef long long ll;
const int N = 1001;
int n, k;
struct data {ll a, b, c; }q[N];
bool cmp(const data& x, const data& y) { return x.c > y.c; }
inline void query(int l, int r) {
int mid = (l + r) >> 1;
for (int i = 0; i < n; ++i)
q[i].c = 100 * q[i].a - mid * q[i].b;
std::sort(q, q + n, cmp);
ll sum = 0;
for (int i = 0; i < n - k; ++i)
sum += q[i].c;
if (sum >= 0) {
if (mid == l) {
ll sb = 0;
for (int i = 0; i < n - k; ++i)
sb += q[i].b;
if (sum << 1LL >= sb)++mid;
printf("%d\n", mid);
return;
}
query(mid, r);
}
else query(l, mid);
}
int main() {
while (1) {
scanf("%d%d", &n, &k);
if (!n && !k)break;
for (int i = 0; i < n; ++i)
scanf("%lld", &q[i].a);
for (int i = 0; i < n; ++i)
scanf("%lld", &q[i].b);
query(0, 100);
}
return 0;
}