Topics
Given two arrays A and B of size N and an integer K. You have to select K indexes such that
is maximum. are all in the range and .
Idea
We can use binary search to find the maximum possible fraction. Thinking in terms of the binary search boolean array framework, we’re searching for the largest x
such that a fraction greater than or equal to x
can be formed. This is like finding the “last true” in a boolean array where check(x)
is true if such a fraction exists. Thus, for a candidate , we want to determine if:
This inequality can be rearranged to:
Or further, to:
For a given x
, the check(x)
function calculates A[i] - x * B[i]
for all i
. Next, we find k largest elements in an array (used sorting here) and check if their sum .
Sufficiency of k-largest elements check
By choosing the
k
largest values ofA[i] - x * B[i]
, we are effectively maximizing the left-hand side of the inequality . If the sum of thesek
largest values is non-negative, it implies that there exists a combination ofk
indices for which the inequality holds true. Conversely, if the sum of thek
largest values is negative, no such combination exists, because any other combination would necessarily have a smaller sum.
If sum is true
, it means we can achieve a fraction of at least x
, so it makes sense to try a larger x
, otherwise, we need to check with a smaller x
. Since x
can be a floating point value, we need to apply binary search on real domain.
Time Complexity: . The check
func uses sorting to find the top k elements resulting in and the binary search runs for 50 iters in our implementation.
Space Complexity: due to the auxiliary array used in the check
function.
Code
bool check(double mid, vector<int> &a, vector<int> &b, int k) {
int n = a.size();
vector<double> aux(n);
for (int i = 0; i < n; ++i) {
aux[i] = a[i] - mid * b[i];
}
// k largest elements
sort(all(aux), greater<double>());
double total = 0;
while (k--) {
total += aux[k];
}
return total >= 0;
}
void solve() {
int n, k;
cin >> n >> k;
vector<int> a(n), b(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
for (int i = 0; i < n; ++i) {
cin >> b[i];
}
double lo = 0;
double hi = 1e4;
double eps = 1e-6;
double ans = 0;
int max_iters = 50;
while (max_iters--) {
double mid = (lo + hi) / 2.0;
if (check(mid, a, b, k)) {
ans = mid;
lo = mid + eps;
} else {
hi = mid - eps;
}
}
cout << fixed << setprecision(6) << ans << '\n';
}