PORX - Editorial

PROBLEM LINK:

Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4

Author: iceknight1093
Tester: sushil2006
Editorialist: iceknight1093

DIFFICULTY:

Simple

PREREQUISITES:

None

PROBLEM:

Given N and X, find any permutation of \{1, 2, \ldots, N\} that maximizes the number of indices satisfying P_i\mid i = X.

EXPLANATION:

We’ll say an integer a is a submask of an integer b, if every bit that’s set in the binary representation of a is also set in the binary representation of b.
For example, 13 equals 1101_2 in binary, and 5 (101_2 in binary) is a submask of it while 2 (10_2 in binary) is not.

For P_i \mid i = X to hold, both P_i and i have to be submasks of X.
In particular, this means that if i is not a submask of X, it doesn’t matter what P_i equals: P_i\mid i will never equal X.

Now, consider some index i such that i is indeed a submask of X.
What should P_i be to make P_i\mid i = X?
Well, P_i should definitely contain all the bits of X that i doesn’t contain.
Observe that since i is a submask of X, these remaining bits will form exactly the value X-i.

Apart from the bits of X-i, P_i can also contain any other bits that are set in both i and X.
However, notice that adding extra bits will only increase the value of P_i, so no matter what, if we want P_i\mid i = X we must have P_i \geq X-i.
In particular, if X-i \gt N, there’s no way to give any valid P_i to index i.

So, we’re left with only a handful of candidate indices: those for which i is a submask of X and X-i \leq N.
It’s easy to see that all of these candidates can be satisfied: just give the value X-i to index i.
The one exception is if i = X, in which case we can’t use the value X - i = 0. However, in this case we can set P_i = X instead (which wouldn’t have been used anywhere else).

After satisfying all these indices, place the remaining elements in the empty spots however you like to complete the permutation.

TIME COMPLEXITY:

\mathcal{O}(N) or \mathcal{O}(N\log N) per testcase.

CODE:

Editorialist's code (C++)
// #include <bits/allocator.h>
// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include "bits/stdc++.h"
using namespace std;
using ll = long long int;
mt19937_64 RNG(chrono::high_resolution_clock::now().time_since_epoch().count());

int main()
{
    ios::sync_with_stdio(false); cin.tie(0);

    int t; cin >> t;
    while (t--) {
        int n, x; cin >> n >> x;
        vector ans(n+1, 0);

        set<int> rem;
        for (int i = 1; i <= n; ++i) rem.insert(i);

		// Satisfy all candidate indices
        for (int i = 1; i <= n; ++i) {
            if (x-i <= n and x-i >= 1) ans[i] = x-i;
            if (i == x) ans[i] = x;
            rem.erase(ans[i]);
        }

		// Fill in empty spots
        for (int i = 1; i <= n; ++i) {
            if (ans[i]) continue;
            ans[i] = *begin(rem);
            rem.erase(ans[i]);
        }
        for (int i = 1; i <= n; ++i) cout << ans[i] << ' ';
        cout << '\n';
    }
}