Apartments
Abridged problem statement
Given two multisets and , and a number , find the size of a maximum matching given that two elements can be matched iff .
That is, form as many pairs with as possible, using every element at most once.
You should take a minute to think about why the original problem statement is equivalent to this abridged version.
Solution
Again, with most greedy problems, there’s really no good way to begin. However, there are things we can try. Allow me to introduce you to another tool you should add to your toolkit: the extremal principle.
The idea behind this problem-solving technique is simple–a complicated problem may be simpler to think about if we consider ’extremal’ cases—that is, cases involving the minimum and maximum elements.
Let’s think about the minimum element across both and , call this , and let’s assume that . Maybe our two sets look something like this:
Here, the blue circles denote elements in (the leftmost blue element is ), and the orange circles denote elements in .
In this case, we cannot match with any element in . Thus, it seems reasonable to assume that the answer will remain unchanged if we remove from ?
But what if the distance between and was ?
We could then match with , but should we?
An optimal matching?
Suppose we already have an optimal matching. If it is possible to modify this matching so that it:
- Remains valid
- Now includes
- Has the same (or better) cardinality as before
then we will have successfully proven that there exists an optimal matching containing . It remains to be seen whether or not this is possible.
To begin with, consider this extremely simple case:
We can simply match with without making any other changes. Next, consider this case:
We can include by removing the existing matching is a part of and matching it with instead. The number of matchings remains unchanged.
The most interesting case is when both and are matched:
I claim that the following replacement is possible:
The proof is straightforward. Let the two matched pairs be and .
We already know that is valid because . We only need to prove that is also valid.
Since and are the minimum elements of their respective sets,
Now consider the relative order of and :
- If (this is what’s depicted in the above diagram), then
because was a valid pair.
- If , then
because was a valid pair.
Therefore, in either case. Thus, we can replace the pairs and with and without changing the matching’s cardinality.
If this is your first time solving this problem, keep in mind that this is a hard and novel idea, and you may benefit from a re-read. Anyway, with all that work, we’ve concluded that matching (when we can) is always optimal. Then, we set
and
When we can’t, it’s safe to discard the smaller of the two.
Implementation
A simple two-pointer approach suffices.
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, k;
cin >> n >> m >> k;
vector<int> a(n), b(m);
for (int &i : a) {
cin >> i;
}
for (int &i : b) {
cin >> i;
}
sort(a.begin(), a.end());
sort(b.begin(), b.end());
int ans = 0;
int i = 0, j = 0;
while (i < int(a.size()) && j < int(b.size())) {
if (abs(a[i] - b[j]) > k) {
if (a[i] < b[j]) {
i++;
} else {
j++;
}
continue;
}
ans++;
i++, j++;
}
cout << ans << '\n';
}