Skip to content

Ferris wheel

Ferris Wheel
CSES
↗

Abridged problem statement

Given an array aa and an integer xx, partition the elements of aa into as few groups as possible. Each group may contain at most two elements, and the sum of its elements must not exceed xx. Determine the minimum number of groups.

Solution

Note: we use the same technique introduced in this article, which may be considered a prerequisite.

Once again, let us employ the extremal principle. Given aa, assuming ∣a∣>1|a| > 1, consider m=min⁡{a}m=\min\{a\} and M=max⁡{a}M=\max\{a\}.

If m+M>xm+M > x, we are forced to create a separate group for MM—it cannot pair with any other element if it can’t pair with the smallest!

If m+M≤xm+M \le x, must we pair MM with mm?

Consider the contrary—that is—consider the case when MM is paired with some other element ee. We have two subcases:

Case #1: mm is unpaired

(symmetric to MM is unpaired, which has been omitted)

In this case, we can simply replace ee with mm, keeping the number of groups the same.

Case #2: mm is paired with some other ff

We know that M+e≤xM+e \le x (turns out we don’t even need to use m+f≤xm+f \le x).

Since m≤em \le e and M+e≤xM+e \le x, M+m≤xM+m \le x as well. But is e+f≤xe+f \le x?

Yes, because e+M≤xe+M \le x and f≤Mf \le M implies e+f≤xe+f \le x.

So, yes, pairing mm with MM really just works. This may seem somewhat magical at first, but we’re actually doing almost the exact same thing as in apartments.

mefM· · ·· · ·· · · mfeM· · ·· · ·· · ·
Before...
mefM· · ·· · ·· · · mfeM· · ·· · ·· · ·
...and after!

Implementation

We maintain a pointer at the front and back.

#include <bits/stdc++.h>

using namespace std;

int main() {
  int n, x;
  cin >> n >> x;
  vector<int> a(n);
  for (int &i : a) {
    cin >> i;
  }
  
  sort(a.begin(), a.end());
  int i = 0, j = a.size() - 1;
  int ans = 0;
  while (i <= j) {
    ans++;
    if (a[i] + a[j] <= x) {
      i++, j--;
    } else {
      j--;
    }
  }

  cout << ans << '\n';
}