Skip to content

Two sets

Two Sets
CSES

Abridged problem statement

Divide the numbers 1,2,3,,n1,2,3,\cdots,n into two sets of equal sum. If this is possible, print YES followed by a valid division. If it is not, print NO.

Solution

To begin with, notice that if

n(n+1)2 \frac{n(n+1)}{2}

that is, the total sum of the numbers, is odd, the answer is always NO, because we cannot divide an odd number into two parts.

On the other hand, if we can produce a valid construction whenever the sum is even, we would be done.

Let us find the first triangular number xx such that

x(x+1)2n(n+1)4\frac{x(x+1)}{2} \ge \frac{n(n+1)}{4}

so

x=1+2n(n+1)12x=\left\lceil \frac{\sqrt{1+2n(n+1)}-1}{2}\right\rceil

Now, we claim that

x(x+1)2n(n+1)4x\frac{x(x+1)}{2} - \frac{n(n+1)}{4} \le x

Indeed, on solving the above inequality, we get

x1+2n(n+1)+12x\le \left\lfloor \frac{\sqrt{1+2n(n+1)}+1}{2}\right\rfloor

and since

c12c+12 \left\lceil \frac{c-1}{2} \right\rceil \le \left\lfloor \frac{c+1}{2} \right\rfloor

for all real cc, the statement is true. Therefore, we sum up the first xx numbers, and then subtract whatever the difference is between our target half-sum and our actual current sum, and add the remaining numbers to the second set.

A more intuitive explanation

The same idea can be proved without any complicated maths if we approach it from the perspective of constructing the other set directly.

That is, we iterate a variable ii from nn down to 11, desiring a total sum of n(n+1)4\frac{n(n+1)}{4}. Call the currently needed sum TT, initially n(n+1)4\frac{n(n+1)}{4}.

  • If iTi \le T, we pick ii and subtract it from TT.
  • Otherwise, T<iT < i. Since we are iterating downward, the number TT itself is still unused, so we can simply pick TT and immediately achieve our target sum.

In fact, we can use this exact same approach to construct any sum from 11 to n(n+1)2\frac{n(n+1)}{2}.

Code

#include <bits/stdc++.h>

using namespace std;

int main() {
  int64_t n;
  cin >> n;

  if ((n * (n + 1) / 2) % 2 == 1) {
    cout << "NO\n";
    return 0;
  }

  int x = ceil((sqrt(1 + 2 * n * (n + 1)) - 1) / 2);
  int exclude = x * (x + 1) / 2 - n * (n + 1) / 4;
  
  vector<int> a, b;
  for (int i = 1; i <= n; ++i) {
    (i != exclude && i <= x ? a : b).push_back(i);
  }

  cout << "YES\n" << a.size() << '\n';
  for (int &i : a) {
    cout << i << ' ';
  }
  cout << '\n' << b.size() << '\n';
  for (int &i : b) {
    cout << i << ' ';
  }
  cout << '\n';
}