Problem: cf1364_e
Difficulty: hard
Categories: bit
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem!

Ehab has a hidden permutation $p$ of length $n$ consisting of the elements from $0$ to $n-1$. You, for some reason, want to figure out the permutation. To do that, you can give Ehab $2$ different indices $i$ and $j$, and he'll reply with $(p_i|p_j)$ where $|$ is the bitwise-or operation.

Ehab has just enough free time to answer $4269$ questions, and while he's OK with answering that many questions, he's too lazy to play your silly games, so he'll fix the permutation beforehand and will not change it depending on your queries. Can you guess the permutation?

Input

The only line contains the integer $n$ $(3 \le n \le 2048)$ — the length of the permutation.

Interaction

To ask a question, print "? $i$ $j$" (without quotes, $i \neq j$) Then, you should read the answer, which will be $(p_i|p_j)$.

If we answer with $-1$ instead of a valid answer, that means you exceeded the number of queries or made an invalid query.

Exit immediately after receiving $-1$ and you will see wrong answer verdict. Otherwise, you can get an arbitrary verdict because your solution will continue to read from a closed stream.

To print the answer, print "! $p_1$ $p_2$ $\ldots$ $p_n$" (without quotes). Note that answering doesn't count as one of the $4269$ queries.

After printing a query or printing the answer, do not forget to output end of line and flush the output. Otherwise, you will get idleness limit exceeded. To do this, use:

* fflush(stdout) or cout.flush() in C++;
* System.out.flush() in Java;
* flush(output) in Pascal;
* stdout.flush() in Python;
* See the documentation for other languages.

Example

Input

```
3
1
3
2
```

Output

```? 1 2? 1 3? 2 3! 1 0 2
```

Note

In the first sample, the permutation is $[1,0,2]$. You start by asking about $p_1|p_2$ and Ehab replies with $1$. You then ask about $p_1|p_3$ and Ehab replies with $3$. Finally, you ask about $p_2|p_3$ and Ehab replies with $2$. You then guess the permutation.

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << '\n';
        tout << "query_limit=" << query_limit << '\n';
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

static bool isIntToken(const string& s) {
    if (s.empty()) return false;
    int i = 0;
    if (s[0] == '-') {
        if ((int)s.size() == 1) return false;
        i = 1;
    }
    for (; i < (int)s.size(); ++i) if (!isdigit((unsigned char)s[i])) return false;
    return true;
}

static bool parseLL(const string& s, long long& out) {
    if (!isIntToken(s)) return false;
    try {
        size_t pos = 0;
        long long v = stoll(s, &pos, 10);
        if (pos != s.size()) return false;
        out = v;
        return true;
    } catch (...) {
        return false;
    }
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    int n = inf.readInt(3, 2048, "n");
    vector<int> p(n);
    for (int i = 0; i < n; ++i) p[i] = inf.readInt(0, n - 1, ("p[" + to_string(i) + "]").c_str());

    
    query_limit = 4269;

    
    log_metrics();

    
    cout << n << endl;

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    string cmd;
    while (true) {
        if (!(cin >> cmd)) {
            finish(_wa, "EOF before printing final answer");
        }

        if (cmd == "?") {
            string si, sj;
            if (!(cin >> si >> sj)) {
                cout << -1 << endl;
                finish(_pe, "malformed query: expected two indices");
            }

            long long i = -1, j = -1;
            if (!parseLL(si, i) || !parseLL(sj, j)) {
                cout << -1 << endl;
                finish(_pe, "malformed query: indices are not integers");
            }

            if (i < 1 || i > n || j < 1 || j > n || i == j) {
                cout << -1 << endl;
                finish(_pe, "invalid query indices");
            }

            ++queries;
            if (queries > hard_cap) {
                cout << -1 << endl;
                finish(_pe, "hard cap exceeded");
            }

            int ans = (p[(int)i - 1] | p[(int)j - 1]);
            cout << ans << endl;
            continue;
        }

        if (cmd == "!") {
            vector<long long> outp_ll(n);
            for (int i = 0; i < n; ++i) {
                string sx;
                if (!(cin >> sx)) finish(_pe, "malformed answer: not enough numbers");
                long long x = -1;
                if (!parseLL(sx, x)) finish(_pe, "malformed answer: non-integer in permutation");
                outp_ll[i] = x;
            }

            vector<int> outp(n);
            vector<char> seen(n, 0);
            for (int i = 0; i < n; ++i) {
                long long x = outp_ll[i];
                if (x < 0 || x >= n) finish(_wa, "answer contains value out of range");
                if (seen[(int)x]) finish(_wa, "answer contains duplicate values");
                seen[(int)x] = 1;
                outp[i] = (int)x;
            }

            for (int i = 0; i < n; ++i) {
                if (outp[i] != p[i]) finish(_wa, "wrong permutation");
            }
            finish(_ok, "correct");
        }

        
        finish(_pe, "unknown command token (expected '?' or '!')");
    }
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

static bool readToken(string& tok) {
    tok.clear();
    if (!(cin >> tok)) return false;
    return true;
}

static bool readLongLong(long long& x) {
    if (!(cin >> x)) return false;
    return true;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n = inf.readInt(3, 2048, "n");

    query_limit = 4269;
    log_metrics(); 

    const long long hard_cap = max(200000LL, 10LL * query_limit);

    
    int k = 0;
    while ((1 << k) <= (n - 1)) ++k;
    int maxMask = (1 << k) - 1;
    if (maxMask < 0) maxMask = 0;

    
    cout << n << "\n";
    cout.flush();

    
    
    
    vector<int> feasibleShifts(n);
    iota(feasibleShifts.begin(), feasibleShifts.end(), 0);

    while (true) {
        string cmd;
        if (!readToken(cmd)) {
            finish(_pe, "unexpected EOF from contestant");
        }

        if (cmd == "?") {
            long long iLL, jLL;
            if (!readLongLong(iLL) || !readLongLong(jLL)) {
                finish(_pe, "malformed query: expected two indices");
            }
            if (iLL < 1 || iLL > n || jLL < 1 || jLL > n) {
                finish(_pe, "invalid query: index out of range");
            }
            if (iLL == jLL) {
                finish(_pe, "invalid query: i == j");
            }

            ++queries;
            if (queries > hard_cap) {
                finish(_pe, "too many queries (hard cap exceeded)");
            }

            int i = int(iLL - 1);
            int j = int(jLL - 1);

            
            
            vector<int> cnt(maxMask + 1, 0);
            for (int s : feasibleShifts) {
                int a = i + s;
                if (a >= n) a -= n;
                int b = j + s;
                if (b >= n) b -= n;
                int x = a | b;
                if (x < 0 || x > maxMask) {
                    finish(_pe, "internal error: OR out of expected range");
                }
                cnt[x]++;
            }

            int bestX = 0;
            int bestC = -1;
            for (int x = 0; x <= maxMask; ++x) {
                int c = cnt[x];
                if (c > bestC || (c == bestC && x > bestX)) {
                    bestC = c;
                    bestX = x;
                }
            }
            if (bestC <= 0) {
                finish(_pe, "internal error: no feasible shifts for query");
            }

            vector<int> nextFeasible;
            nextFeasible.reserve(bestC);
            for (int s : feasibleShifts) {
                int a = i + s;
                if (a >= n) a -= n;
                int b = j + s;
                if (b >= n) b -= n;
                if ((a | b) == bestX) nextFeasible.push_back(s);
            }
            if (nextFeasible.empty()) {
                finish(_pe, "internal error: filtering produced empty feasible set");
            }
            feasibleShifts.swap(nextFeasible);

            cout << bestX << "\n";
            cout.flush();
        } else if (cmd == "!") {
            vector<long long> outLL(n);
            for (int idx = 0; idx < n; ++idx) {
                if (!readLongLong(outLL[idx])) {
                    finish(_pe, "malformed answer: expected n integers after '!'");
                }
            }

            vector<int> out(n);
            vector<char> seen(n, 0);
            for (int idx = 0; idx < n; ++idx) {
                long long v = outLL[idx];
                if (v < 0 || v >= n) finish(_pe, "malformed answer: value out of range");
                if (seen[(int)v]) finish(_pe, "malformed answer: duplicate value");
                seen[(int)v] = 1;
                out[idx] = (int)v;
            }

            
            
            for (int s : feasibleShifts) {
                bool ok = true;
                for (int pos = 0; pos < n; ++pos) {
                    int expect = pos + s;
                    if (expect >= n) expect -= n;
                    if (out[pos] != expect) {
                        ok = false;
                        break;
                    }
                }
                if (!ok) {
                    finish(_wa, "answer is not correct for all feasible instances");
                }
            }

            finish(_ok, "correct");
        } else {
            finish(_pe, "invalid command token (expected '?' or '!')");
        }
    }
}


Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static bool isPow2(int n) {
    return n > 0 && (n & (n - 1)) == 0;
}

static int popcnt(int x) {
    return __builtin_popcount((unsigned)x);
}

static void shuffleVec(vector<int>& a) {
    for (int i = (int)a.size() - 1; i > 0; --i) {
        int j = rnd.next(0, i);
        swap(a[i], a[j]);
    }
}

static void shufflePairs(vector<pair<int,int>>& a) {
    for (int i = (int)a.size() - 1; i > 0; --i) {
        int j = rnd.next(0, i);
        swap(a[i], a[j]);
    }
}

static vector<int> makePairPermutation(int n, int mask, bool keepPairsAdjacent) {
    vector<char> used(n, 0);
    vector<pair<int,int>> pairs;
    vector<int> leftovers;
    pairs.reserve(n / 2);

    for (int x = 0; x < n; ++x) {
        if (used[x]) continue;
        int y = x ^ mask;
        if (y >= 0 && y < n && y != x && !used[y]) {
            used[x] = used[y] = 1;
            pairs.push_back({x, y});
        } else {
            used[x] = 1;
            leftovers.push_back(x);
        }
    }

    shufflePairs(pairs);
    shuffleVec(leftovers);

    stable_sort(leftovers.begin(), leftovers.end(), [&](int a, int b) {
        int pa = popcnt(a), pb = popcnt(b);
        if (pa != pb) return pa > pb;
        return a < b;
    });

    vector<int> p;
    p.reserve(n);

    if (keepPairsAdjacent) {
        for (auto [a, b] : pairs) {
            if (rnd.next(0, 1) == 0) {
                p.push_back(a);
                p.push_back(b);
            } else {
                p.push_back(b);
                p.push_back(a);
            }
        }
        for (int x : leftovers) p.push_back(x);
    } else {
        vector<int> pool;
        pool.reserve(n);
        for (auto [a, b] : pairs) {
            if (rnd.next(0, 1) == 0) {
                pool.push_back(a);
                pool.push_back(b);
            } else {
                pool.push_back(b);
                pool.push_back(a);
            }
        }
        for (int x : leftovers) pool.push_back(x);
        shuffleVec(pool);
        p.swap(pool);
    }

    if ((int)p.size() != n) {
        
        p.clear();
        for (int i = 0; i < n; ++i) p.push_back(i);
        shuffleVec(p);
    }
    return p;
}

static vector<int> makeBitReversalPermutation(int n) {
    int k = 0;
    while ((1 << k) < n) ++k; 
    int mask = n - 1;
    int xorMask = rnd.next(0, mask);
    int shift = rnd.next(0, n - 1);

    vector<int> p(n);
    for (int i = 0; i < n; ++i) {
        int x = i;
        int r = 0;
        for (int b = 0; b < k; ++b) {
            r = (r << 1) | (x & 1);
            x >>= 1;
        }
        r ^= xorMask;
        p[(i + shift) & mask] = r;
    }
    return p;
}

static vector<int> makeGrayPermutation(int n) {
    int mask = n - 1;
    int xorMask = rnd.next(0, mask);
    int shift = rnd.next(0, n - 1);

    vector<int> p(n);
    for (int i = 0; i < n; ++i) {
        int g = i ^ (i >> 1);
        g ^= xorMask;
        p[(i + shift) & mask] = g;
    }
    return p;
}

static vector<int> makeRandomPermutation(int n) {
    vector<int> p(n);
    iota(p.begin(), p.end(), 0);
    shuffleVec(p);
    return p;
}

static void printPermutation(const vector<int>& p) {
    for (int i = 0; i < (int)p.size(); ++i) {
        if (i) cout << ' ';
        cout << p[i];
    }
    cout << "\n";
}

int main(int argc, char** argv) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");
    string pattern = opt<string>("pattern", "auto");
    int nOpt = opt<int>("n", 0);

    long long seed = 0;
    if (argc >= 2) {
        
        seed = atoll(argv[1]);
    }

    int n = 0;
    if (seed == 1) {
        n = 3;
    } else if (seed == 2) {
        n = 2048;
    } else if (seed == 3) {
        n = 2047;
    } else if (nOpt >= 3) {
        n = nOpt;
    } else {
        
        n = (seed % 17 == 0 ? 2047 : 2048);
    }

    if (mode != "non" && mode != "adp") mode = "non";

    if (mode == "adp") {
        
        cout << n << "\n";
        return 0;
    }

    
    cout << n << "\n";

    vector<int> p;
    if (seed == 1) {
        p = {1, 0, 2};
        printPermutation(p);
        return 0;
    }
    if (seed == 2) {
        p.reserve(n);
        for (int x = 0; x < n / 2; ++x) {
            p.push_back(x);
            p.push_back((n - 1) - x);
        }
        printPermutation(p);
        return 0;
    }
    if (seed == 3) {
        int mask = (1 << 11) - 1; 
        p.reserve(n);
        p.push_back(0);
        for (int x = 1; x <= 1023; ++x) {
            int y = x ^ mask; 
            p.push_back(x);
            p.push_back(y);
        }
        printPermutation(p);
        return 0;
    }

    if (pattern == "auto") {
        if (isPow2(n)) {
            int t = (int)(seed % 3);
            if (t == 0) pattern = "pair";
            else if (t == 1) pattern = "rev";
            else pattern = "gray";
        } else {
            pattern = "pair";
        }
    }

    if (pattern == "pair") {
        int k = 0;
        while ((1 << k) < n) ++k;
        int mask = (1 << k) - 1;
        bool keepAdjacent = true;
        p = makePairPermutation(n, mask, keepAdjacent);
    } else if (pattern == "rev") {
        if (isPow2(n)) p = makeBitReversalPermutation(n);
        else p = makeRandomPermutation(n);
    } else if (pattern == "gray") {
        if (isPow2(n)) p = makeGrayPermutation(n);
        else p = makeRandomPermutation(n);
    } else if (pattern == "rand") {
        p = makeRandomPermutation(n);
    } else {
        
        int k = 0;
        while ((1 << k) < n) ++k;
        int mask = (1 << k) - 1;
        p = makePairPermutation(n, mask, true);
    }

    printPermutation(p);
    return 0;
}