Problem: cf2173_e
Difficulty: medium
Categories: greedy, data structures
Time limit: 3000 ms, memory limit: 256 MB

There's no such thing as luck in this world. The victor is decided before the game even starts.

— No Game No Life

This is an interactive problem.

One day, Sora and Shiro feel bored again, so they decide to settle it with a game.

At the beginning, Sora gives Shiro a permutation$$$^{\text{∗}}$$$ $$$p\_1,p\_2,\ldots,p\_n$$$ of length $$$n$$$. In each operation, Shiro may select two distinct indices $$$x$$$ and $$$y$$$ ($$$1\le x\ne y\le n$$$). Then Sora flips a fair coin:

* With probability $$$0.5$$$, Sora swaps $$$p\_x$$$ and $$$p\_y$$$;
* With probability $$$0.5$$$, Sora swaps $$$p\_{n-x+1}$$$ and $$$p\_{n-y+1}$$$.

After the operation, Sora replies with the actual pair of indices that were swapped, so that Shiro can update her local permutation accordingly.

Shiro's goal is to sort the permutation $$$p$$$ in ascending order by using at most $$$\lfloor 2.5n+800\rfloor$$$ operations. Help her!

$$$^{\text{∗}}$$$A permutation of length $$$n$$$ is an array consisting of $$$n$$$ distinct integers from $$$1$$$ to $$$n$$$ in arbitrary order. For example, $$$[2,3,1,5,4]$$$ is a permutation, but $$$[1,2,2]$$$ is not a permutation ($$$2$$$ appears twice in the array), and $$$[1,3,4]$$$ is also not a permutation ($$$n=3$$$ but there is $$$4$$$ in the array).

Input

Each test contains multiple test cases. The first line contains the number of test cases $$$t$$$ ($$$1 \le t \le 100$$$). The description of the test cases follows.

The first line of each test case contains a single integer $$$n$$$ ($$$1\le n\le 4000$$$) — the length of $$$p$$$.

The second line contains $$$n$$$ integers $$$p\_1,p\_2,\ldots,p\_n$$$ — the elements of $$$p$$$.

It is guaranteed that the sum of $$$n$$$ over all test cases does not exceed $$$2\cdot 10^4$$$.

It is guaranteed that there are $$$50$$$ tests in this problem.

Interaction

For each test case, you can use at most $$$\lfloor 2.5n+800\rfloor$$$ moves to sort the permutation $$$p$$$ in ascending order.

To make a move, you should print a new line in the following format:

* $$$\mathtt{?}\; x\; y$$$ ($$$1 \le x \ne y \le n$$$) — the two indices that Shiro selects in this move.

As a response to the move, you will receive two integers $$$u$$$ and $$$v$$$ — the actual pair of indices that Sora swapped. It is guaranteed that $$$(u, v)$$$ is randomly selected from $$$(x, y)$$$ and $$$(n-x+1, n-y+1)$$$ with equal probability.

To report that the permutation has been sorted in ascending order, you should print a new line with a single character $$$\mathtt{!}$$$. This does not count as one of the $$$\lfloor 2.5n+800\rfloor$$$ moves.

After that, proceed to the next test case or terminate the program if it was the last test case.

After printing each query do not forget to output the end of line and flush$$$^{\text{∗}}$$$ the output. Otherwise, you will get Idleness limit exceeded verdict.

If, at any interaction step, you read $$$-1$$$ instead of valid data, your solution must exit immediately. This means that your solution will receive Wrong answer because of an invalid query or any other mistake. Failing to exit can result in an arbitrary verdict because your solution will continue to read from a closed stream.

$$$^{\text{∗}}$$$To flush, use:

* fflush(stdout) or cout.flush() in C++;
* sys.stdout.flush() in Python;
* see the documentation for other languages.

Example

Input

```
2
5
5 1 3 4 2

1 5

2 1

2
1 2
```

Output

```
? 1 5

? 4 5

!

!
```

Note

In the first test case, $$$n=5$$$ and the initial permutation is $$$[5,1,3,4,2]$$$.

* We print ? 1 5. The judge replies 1 5, meaning positions $$$1$$$ and $$$5$$$ are swapped (no mirroring). The array becomes $$$[2,1,3,4,5]$$$.
* We print ? 4 5. The judge replies 2 1, which is the mirror of $$${4,5}$$$ because with $$$n=5$$$ we have $$$n-4+1=2$$$ and $$$n-5+1=1$$$. Thus we must swap positions $$$2$$$ and $$$1$$$. The array becomes $$$[1,2,3,4,5]$$$.
* The permutation is now sorted, so we print !. The answer line does not count toward the operation limit.

In the second test case, the given permutation is already increasing, so we just need to output !.

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 << endl;
        tout << "query_limit=" << query_limit << endl;
    } catch (...) {
        
    }
}

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

static uint64_t splitmix64(uint64_t x) {
    x += 0x9e3779b97f4a7c15ULL;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
    x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
    return x ^ (x >> 31);
}

struct TestCase {
    int n;
    vector<int> p;    
    vector<int> pos;  
    uint64_t seed;
};

static bool isSorted(const vector<int>& p) {
    for (int i = 1; i < (int)p.size(); ++i) {
        if (p[i] != i) return false;
    }
    return true;
}

static uint64_t hashPermutation(int n, const vector<int>& p) {
    uint64_t h = 0x243f6a8885a308d3ULL ^ (uint64_t)n * 0x9e3779b97f4a7c15ULL;
    for (int i = 1; i <= n; ++i) {
        uint64_t x = (uint64_t)p[i];
        uint64_t mix = x + 0x9e3779b97f4a7c15ULL * (uint64_t)i;
        h = splitmix64(h ^ mix);
    }
    return h;
}

static int coinFlip(const TestCase& tc, long long qidx1based) {
    
    uint64_t v = splitmix64(tc.seed + (uint64_t)qidx1based * 0x9e3779b97f4a7c15ULL);
    return (int)((v >> 63) & 1ULL);
}

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

    int t = inf.readInt(1, 100, "t");
    vector<TestCase> tests;
    tests.reserve(t);

    long long total_limit = 0;
    for (int tc = 0; tc < t; ++tc) {
        int n = inf.readInt(1, 4000, "n");
        vector<int> p(n + 1), pos(n + 1, 0);
        vector<char> seen(n + 1, 0);
        for (int i = 1; i <= n; ++i) {
            int v = inf.readInt(1, n, "p[i]");
            if (seen[v]) finish(_fail, "Invalid hidden input: not a permutation");
            seen[v] = 1;
            p[i] = v;
            pos[v] = i;
        }
        TestCase cs;
        cs.n = n;
        cs.p = std::move(p);
        cs.pos = std::move(pos);
        cs.seed = hashPermutation(n, cs.p);

        long long B = (5LL * n) / 2LL + 800LL; 
        total_limit += B;
        tests.push_back(std::move(cs));
    }

    query_limit = total_limit;
    log_metrics(); 

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

    cout << t << endl; 
    cout.flush();

    for (int tc = 0; tc < t; ++tc) {
        TestCase& cs = tests[tc];
        int n = cs.n;

        cout << n << endl;
        for (int i = 1; i <= n; ++i) {
            if (i > 1) cout << ' ';
            cout << cs.p[i];
        }
        cout << endl;
        cout.flush();

        long long qidx = 0;
        while (true) {
            string cmd;
            if (!(cin >> cmd)) finish(_pe, "Unexpected EOF from contestant");

            if (cmd == "!") {
                if (!isSorted(cs.p)) finish(_wa, "Contestant finished but permutation is not sorted");
                break;
            }

            if (cmd != "?") finish(_pe, "Invalid command (expected '?' or '!')");

            long long xll, yll;
            if (!(cin >> xll >> yll)) finish(_pe, "Malformed query: expected two integers after '?'");
            if (xll < 1 || xll > n || yll < 1 || yll > n) finish(_wa, "Query indices out of range");
            if (xll == yll) finish(_wa, "Query indices must be distinct");

            ++queries;
            ++qidx;
            if (queries > hard_cap) finish(_pe, "Hard cap exceeded (likely infinite loop/output spam)");

            int x = (int)xll, y = (int)yll;
            int u = x, v = y;
            if (coinFlip(cs, qidx) == 1) {
                u = n - x + 1;
                v = n - y + 1;
            }

            
            int a = cs.p[u];
            int b = cs.p[v];
            cs.p[u] = b;
            cs.p[v] = a;
            cs.pos[a] = v;
            cs.pos[b] = u;

            cout << u << " " << v << endl;
            cout.flush();

            
            if ((queries & 1023LL) == 0) log_metrics();
        }
    }

    
    {
        string extra;
        if (cin >> extra) finish(_pe, "Extra output after finishing all test cases");
    }

    finish(_ok, "OK");
    return 0;
}


Adaptive interactor (C++):

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

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

static vector<int> buildHandCrafted(int seed) {
    if (seed == 1) {
        return vector<int>{1};
    }
    if (seed == 2) {
        return vector<int>{2, 1};
    }
    
    int n = 3999;
    int m = n / 2; 
    vector<int> p(n, 0);
    
    
    
    
    
    
    for (int i = 1; i <= m; ++i) p[i - 1] = (m + 1) + i;     
    p[m] = m + 1;                                           
    for (int i = 1; i <= m; ++i) p[m + i] = i;              

    
    swap(p[0], p[m]);

    
    for (int r = 0; r < 700; ++r) {
        int i = rnd.next(1, n);
        int j = n - i + 1;
        if (i == j) continue;
        swap(p[i - 1], p[j - 1]);
    }

    
    int shift = rnd.next(1, n - 1);
    rotate(p.begin(), p.begin() + shift, p.end());
    return p;
}

static vector<int> buildHardRandom(int n) {
    int m = n / 2;
    vector<int> p(n, 0);

    if (n % 2 == 0) {
        vector<int> A(m), B(m);
        for (int i = 0; i < m; ++i) A[i] = i + 1;
        for (int i = 0; i < m; ++i) B[i] = m + 1 + i;

        fyShuffle(A);
        fyShuffle(B);

        
        for (int i = 0; i < m; ++i) {
            p[i] = B[i];
            p[i + m] = A[i];
        }
    } else {
        
        vector<int> A(m), B(m);
        for (int i = 0; i < m; ++i) A[i] = i + 1;
        for (int i = 0; i < m; ++i) B[i] = (m + 2) + i;

        fyShuffle(A);
        fyShuffle(B);

        for (int i = 0; i < m; ++i) p[i] = B[i];
        p[m] = m + 1;
        for (int i = 0; i < m; ++i) p[m + 1 + i] = A[i];

        
        int pos = (rnd.next(0, 1) == 0 ? 0 : n - 1);
        swap(p[m], p[pos]);
    }

    
    int mirrorOps = min(1200, n);
    for (int r = 0; r < mirrorOps; ++r) {
        int i = rnd.next(1, n);
        int j = n - i + 1;
        if (i == j) continue;
        swap(p[i - 1], p[j - 1]);
    }

    
    int extraOps = min(1800, n);
    for (int r = 0; r < extraOps; ++r) {
        int i = rnd.next(1, n);
        int j = rnd.next(1, n);
        if (i == j) continue;
        swap(p[i - 1], p[j - 1]);
    }

    
    int shift = rnd.next(0, n - 1);
    rotate(p.begin(), p.begin() + shift, p.end());
    return p;
}

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

    int seed = 1;
    if (argc > 1) seed = atoi(argv[1]);

    string mode = opt<string>("mode", "non");
    int forcedN = opt<int>("n", -1);

    int n;
    vector<int> p;

    if (seed >= 1 && seed <= 3 && forcedN == -1) {
        p = buildHandCrafted(seed);
        n = (int)p.size();
    } else {
        if (forcedN != -1) {
            n = forcedN;
        } else {
            
            
            int lo = opt<int>("nmin", 3500);
            int hi = opt<int>("nmax", 4000);
            lo = max(lo, 1);
            hi = min(hi, 4000);
            if (lo > hi) lo = hi;
            n = rnd.next(lo, hi);
            if (n >= 3 && rnd.next(0, 3) == 0) {
                if (n % 2 == 0) n -= 1;
            }
        }
        n = max(1, min(4000, n));
        if (n == 1) {
            p = vector<int>{1};
        } else if (n == 2) {
            p = vector<int>{2, 1};
        } else {
            p = buildHardRandom(n);
        }
    }

    
    if (mode == "non") {
        cout << 1 << "\n";
        cout << n << "\n";
        for (int i = 0; i < n; ++i) {
            if (i) cout << ' ';
            cout << p[i];
        }
        cout << "\n";
    } else if (mode == "adp") {
        cout << 1 << "\n";
        cout << n << "\n";
        for (int i = 0; i < n; ++i) {
            if (i) cout << ' ';
            cout << p[i];
        }
        cout << "\n";
    } else {
        quitf(_fail, "Unknown --mode (expected 'non' or 'adp')");
    }

    return 0;
}