#pragma GCC optimize("Ofast")

#include "bits/stdc++.h"
#include "checkpoint.h"


#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i < (n); ++i)
#define rep1n(i, n) for (int i = 1; i <= (n); ++i)
#define repr(i, n) for (int i = (n) - 1; i >= 0; --i)
#define pb push_back
#define eb emplace_back
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define each(x, a) for (auto &x : a)
#define ar array
#define vec vector
#define range(i, n) rep(i, n)

using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using str = string;
using pi = pair<int, int>;
using pl = pair<ll, ll>;

using vi = vector<int>;
using vl = vector<ll>;
using vpi = vector<pair<int, int>>;
using vvi = vector<vi>;

int Bit(int mask, int b) { return (mask >> b) & 1; }

template<class T>
bool ckmin(T &a, const T &b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
bool ckmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

// [l, r)
template<typename T, typename F>
T FindFirstTrue(T l, T r, const F &predicat) {
    --l;
    while (r - l > 1) {
        T mid = l + (r - l) / 2;
        if (predicat(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    return r;
}


template<typename T, typename F>
T FindLastFalse(T l, T r, const F &predicat) {
    return FindFirstTrue(l, r, predicat) - 1;
}

const int INFi = 1e9;
const ll INF = 2e18;
const int LG = 20;

struct Solver {
    map<pair<int, int>, int> mem;

    int ask(int i, int j) {
        if (i == j) return i;
        if (i > j) swap(i, j);
        if (mem.count({i, j})) return mem[{i, j}];
        return mem[{i, j}] = min_value(i, j);
    }
};

struct Group {
    vi values;
    int lq, rq;

    int size() {
        return values.size();
    }

    bool contains(int pos) {
        return lq <= pos && pos < rq;
    }
};


std::vector<int> guess(int n) {
    vi p(n, -1), inv_p(n + 1, -1);
    if (n <= 3) {
        iota(all(p), 1);
        return p;
    }
    vector<Group> groups;
    groups.push_back({.values = {}, .lq = 1, .rq = n});
    for (int i = 2; i <= n; ++i) groups.back().values.push_back(i);
    Solver s;

    auto GetOpposite = [&](int r_mid) {
        r_mid += n / 2;
        r_mid %= n;
        return r_mid;
    };

    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

    vector<int> to_fix;

    auto SetValue = [&](int i, int x) {
        assert(0 <= i && i < n && 1 <= x && x <= n);
        if (p[i] != -1) assert(p[i] == x);
        if (inv_p[x] != -1) assert(inv_p[x] == i);
        p[i] = x;
        inv_p[x] = i;
    };

    auto TryFix = [&]() {
        sort(all(to_fix));
        to_fix.resize(unique(all(to_fix)) - to_fix.begin());
        while (!to_fix.empty()) {
            int gi = to_fix.back();
            to_fix.pop_back();
            auto &g = groups[gi];
            int cnt_unk = count(p.begin() + g.lq, p.begin() + g.rq, -1);
            if (cnt_unk == 1) {
                int pos = find(p.begin() + g.lq, p.begin() + g.rq, -1) - p.begin();
                assert(g.contains(pos) && p[pos] == -1);
                for (auto &t: g.values) {
                    if (inv_p[t] == -1) {
                        SetValue(pos, t);
                        break;
                    }
                }
                assert(p[pos] != -1);
            }
            if (cnt_unk <= 1) {
                groups.erase(groups.begin() + gi);
            }
        }
    };

    auto FindCool = [&] (int pos) {
        if (p[pos] != -1) {
            return p[pos];
        } else {
            int split_group = 0;
            while (split_group < groups.size() && !groups[split_group].contains(pos)) split_group++;

            assert(split_group < groups.size() && groups[split_group].contains(pos));
            to_fix.push_back(split_group);
            return groups[split_group].values[rng() % groups[split_group].size()];
        }
    };

    SetValue(0, 1);
    for (; !groups.empty(); TryFix()) {
        int big = 0;
        rep(i, groups.size()) {
            if (groups[big].size() > groups[i].size()) continue;
            if (groups[big].size() == groups[i].size() && groups[i].lq == n / 2 && groups[i].rq == n / 2 + 2) continue;
            big = i;
        }

        auto &g = groups[big];

        int mid = (g.lq + g.rq) / 2;

        int pos = GetOpposite(mid);
        if (pos == 0 && (g.rq - g.lq) >= 3) pos++;

        if (pos == 0) {
            assert(g.lq == n / 2 && g.rq == n / 2 + 2);
            assert(groups.size() == 1);
            // so i need last kek

            int x = g.values[0];
            int y = g.values[1];
            if (x > y) swap(x, y);

            if (p[g.lq - 1] > x) {
                if (s.ask(p[g.lq - 1], y) != x) {
                    swap(x, y);
                }
            } else if (p[g.rq] > x) {
                if (s.ask(p[g.rq], y) == x) {
                    swap(x, y);
                }
            }
            SetValue(g.lq, x);
            SetValue(g.lq + 1, y);
            to_fix.emplace_back(0);
            TryFix();
            assert(groups.empty());
            break;
        }

        if (groups[big].contains(pos)) assert(g.size() == n - 1);

        int cool = FindCool(pos);

        vi ones, twos;
        for (auto t: groups[big].values) {
            if (s.ask(t, cool) == 1) {
                ones.emplace_back(t);
            } else {
                twos.emplace_back(t);
            }
        }

        if (ones.empty() || twos.empty()) continue;
        to_fix.emplace_back(groups.size());

        if (groups[big].size() == n - 1) {
            // one group
            SetValue(n - n / 2 + (int)ones.size(), cool);
            g.values = ones;
            g.lq = 1;
            g.rq = g.lq + (int)ones.size();
            Group g2{.values = twos, .lq = g.rq, .rq = n};
            groups.emplace_back(g2);
            continue;
        }

        to_fix.emplace_back(big);

        if (pos < g.lq) {
            Group g2;
            g2.values = ones;
            g.values = twos;
            g2.rq = g.rq;
            g2.lq = g.rq = g.lq + (int)twos.size();
            groups.emplace_back(g2);
            SetValue(g2.lq + n / 2 - n, cool);
            continue;
        }

        if (pos >= g.rq) {
            Group g2;
            g2.values = twos;
            g.values = ones;
            g2.rq = g.rq;
            g2.lq = g.rq = g.lq + (int)ones.size();
            groups.emplace_back(g2);
            SetValue(g2.lq - 1 - n / 2 + n, cool);
            continue;
        }

        assert(0);
    }

    assert(count(all(p), -1) == 0);
    return p;
}