Problem: cf2032_d
Difficulty: hard
Categories: graph, greedy, data structures
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem.

Upon clearing the Waterside Area, Gretel has found a monster named Genokraken, and she's keeping it contained for her scientific studies.

The monster's nerve system can be structured as a tree$^{\dagger}$ of $n$ nodes (really, everything should stop resembling trees all the time$\ldots$), numbered from $0$ to $n-1$, with node $0$ as the root.

Gretel's objective is to learn the exact structure of the monster's nerve system — more specifically, she wants to know the values $p_1, p_2, \ldots, p_{n-1}$ of the tree, where $p_i$ ($0 \le p_i < i$) is the direct parent node of node $i$ ($1 \le i \le n - 1$).

She doesn't know exactly how the nodes are placed, but she knows a few convenient facts:

* If we remove root node $0$ and all adjacent edges, this tree will turn into a forest consisting of only paths$^{\ddagger}$. Each node that was initially adjacent to the node $0$ will be the end of some path.
* The nodes are indexed in a way that if $1 \le x \le y \le n - 1$, then $p_x \le p_y$.
* Node $1$ has exactly two adjacent nodes (including the node $0$).

|  |  |  |
| --- | --- | --- |
|  |  |  |
| The tree in this picture does not satisfy the condition, because if we remove node $0$, then node $2$ (which was initially adjacent to the node $0$) will not be the end of the path $4-2-5$. | The tree in this picture does not satisfy the condition, because $p_3 \le p_4$ must hold. | The tree in this picture does not satisfy the condition, because node $1$ has only one adjacent node. |

Gretel can make queries to the containment cell:

* "? a b" ($1 \le a, b < n$, $a \ne b$) — the cell will check if the simple path between nodes $a$ and $b$ contains the node $0$.

However, to avoid unexpected consequences by overstimulating the creature, Gretel wants to query at most $2n - 6$ times. Though Gretel is gifted, she can't do everything all at once, so can you give her a helping hand?

$^{\dagger}$A tree is a connected graph where every pair of distinct nodes has exactly one simple path connecting them.

$^{\ddagger}$A path is a tree whose vertices can be listed in the order $v_1, v_2, \ldots, v_k$ such that the edges are $(v_i, v_{i+1})$ ($1 \le i < k$).

Input

Each test consists of multiple test cases. The first line contains a single integer $t$ ($1 \le t \le 500$) — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer $n$ ($4 \le n \le 10^4$) — the number of nodes in Genokraken's nerve system.

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

Interaction

For each test case, interaction starts by reading the integer $n$.

Then you can make queries of the following type:

* "? a b" (without quotes) ($1 \le a, b < n$, $a \ne b$).

After the query, read an integer $r$ — the answer to your query. You are allowed to use at most $2n - 6$ queries of this type.

* If the simple path between nodes $a$ and $b$ does not contain node $0$, you will get $r = 0$.
* If the simple path between nodes $a$ and $b$ contains node $0$, you will get $r = 1$.
* In case you make more than $2n-6$ queries or make an invalid query, you will get $r = -1$. You will need to terminate after this to get the "Wrong answer" verdict. Otherwise, you can get an arbitrary verdict because your solution will continue to read from a closed stream.

When you find out the structure, output a line in the format "! $p_1 \space p_2 \ldots p_{n-1}$" (without quotes), where $p_i$ ($0 \le p_i < i$) denotes the index of the direct parent of node $i$. This query is not counted towards the $2n - 6$ queries limit.

After solving one test case, the program should immediately move on to the next one. After solving all test cases, the program should be terminated immediately.

After printing any query do not forget to output an end of line and flush the output buffer. 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 documentation for other languages.

The interactor is non-adaptive. The tree does not change during the interaction.

Example

Input

```
3
4

1

5

1

0

9
```

Output

```
? 2 3

! 0 0 1

? 2 3

? 2 4

! 0 0 1 2

! 0 0 0 1 3 5 6 7
```

Note

In the first test case, Genokraken's nerve system forms the following tree:

 ![](https://espresso.codeforces.com/18420aff286c55d32046199104d02ecde37edebb.png) 

* The answer to "? 2 3" is $1$. This means that the simple path between nodes $2$ and $3$ contains node $0$.

In the second test case, Genokraken's nerve system forms the following tree:

 ![](https://espresso.codeforces.com/59d76503b8daf3ad700c1899663c151400690dae.png) 

* The answer to "? 2 3" is $1$. This means that the simple path between nodes $2$ and $3$ contains node $0$.
* The answer to "? 2 4" is $0$. This means that the simple path between nodes $2$ and $4$ doesn't contain node $0$.

In the third test case, Genokraken's nerve system forms the following tree:

 ![](https://espresso.codeforces.com/bca4f36fd8100724058d3ac595a5d1ef4116453f.png)

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 readToken(string& s) {
    if (!(cin >> s)) return false;
    return true;
}

static bool parseLL(const string& s, long long& out) {
    if (s.empty()) return false;
    int i = 0;
    bool neg = false;
    if (s[i] == '+' || s[i] == '-') {
        neg = (s[i] == '-');
        i++;
        if (i == (int)s.size()) return false;
    }
    __int128 val = 0;
    for (; i < (int)s.size(); i++) {
        char c = s[i];
        if (c < '0' || c > '9') return false;
        val = val * 10 + (c - '0');
        if (!neg && val > (__int128)LLONG_MAX) return false;
        if (neg && -val < (__int128)LLONG_MIN) return false;
    }
    out = neg ? (long long)(-val) : (long long)val;
    return true;
}

static bool readLL(long long& v) {
    string s;
    if (!readToken(s)) return false;
    return parseLL(s, v);
}

struct TestCase {
    int n = 0;
    vector<int> parent;    
    vector<int> rootChild; 
};

static TestCase loadCaseFromInf() {
    TestCase tc;
    tc.n = inf.readInt(4, 10000, "n");
    tc.parent.assign(tc.n, -1);
    tc.parent[0] = -1;
    for (int i = 1; i < tc.n; i++) {
        int p = inf.readInt(0, i - 1, ("p_" + to_string(i)).c_str());
        tc.parent[i] = p;
    }

    vector<vector<int>> children(tc.n);
    children[0].reserve(tc.n);
    for (int i = 1; i < tc.n; i++) children[tc.parent[i]].push_back(i);

    tc.rootChild.assign(tc.n, -1);
    tc.rootChild[0] = 0;

    queue<int> q;
    for (int c : children[0]) {
        tc.rootChild[c] = c;
        q.push(c);
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int u : children[v]) {
                tc.rootChild[u] = c;
                q.push(u);
            }
        }
    }

    for (int i = 1; i < tc.n; i++) {
        if (tc.rootChild[i] == -1) quitf(_fail, "Internal error: node %d not reachable from root 0", i);
    }
    return tc;
}

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

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

    long long totalBudget = 0;
    for (int tc = 0; tc < t; tc++) {
        TestCase one = loadCaseFromInf();
        totalBudget += (long long)2 * one.n - 6;
        cases.push_back(std::move(one));
    }

    query_limit = totalBudget;
    log_metrics(); 

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

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

    for (int tc = 0; tc < t; tc++) {
        const int n = cases[tc].n;
        const vector<int>& parent = cases[tc].parent;
        const vector<int>& rootChild = cases[tc].rootChild;

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

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

            if (cmd == "?") {
                long long a_ll, b_ll;
                if (!readLL(a_ll) || !readLL(b_ll)) finish(_pe, "Malformed query: expected two integers");
                if (a_ll < 1 || a_ll >= n || b_ll < 1 || b_ll >= n) finish(_pe, "Invalid query indices");
                if (a_ll == b_ll) finish(_pe, "Invalid query: a == b");

                queries++;
                if (queries > hard_cap) finish(_pe, "Hard cap exceeded");

                int a = (int)a_ll, b = (int)b_ll;
                int ans = (rootChild[a] != rootChild[b]) ? 1 : 0;

                cout << ans << "\n";
                cout.flush();
            } else if (cmd == "!") {
                for (int i = 1; i < n; i++) {
                    long long x;
                    if (!readLL(x)) finish(_pe, "Malformed answer: not enough integers after '!'");
                    if (x < 0 || x >= i) finish(_wa, "Answer has invalid parent value");
                    if ((int)x != parent[i]) finish(_wa, "Wrong parent array");
                }
                break;
            } else {
                finish(_pe, "Unknown command token");
            }
        }
    }

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


Adaptive interactor (C++):

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

static vector<int> buildParentsFromChainLengths(int n, const vector<int>& len) {
    int m = (int)len.size();
    vector<int> parent(n, -1);
    vector<int> last(m, 0);
    int cur = 0;

    int maxLen = 0;
    for (int x : len) maxLen = max(maxLen, x);

    for (int depth = 1; depth <= maxLen; depth++) {
        for (int i = 0; i < m; i++) {
            if (depth > len[i]) continue;
            cur++;
            if (depth == 1) parent[cur] = 0;
            else parent[cur] = last[i];
            last[i] = cur;
        }
    }

    ensuref(cur == n - 1, "Internal error: constructed %d nodes, expected %d", cur, n - 1);

    for (int i = 1; i < n; i++) {
        ensuref(0 <= parent[i] && parent[i] < i, "Invalid parent[%d]=%d", i, parent[i]);
    }

    
    int deg1 = 0;
    for (int i = 0; i < n; i++) {
        if (i == 1) {
            if (parent[i] != -1) deg1++;
        } else if (i > 1) {
            if (parent[i] == 1) deg1++;
            if (parent[1] == i) deg1++;
        }
    }
    ensuref(deg1 == 2, "Node 1 degree must be 2, got %d", deg1);

    
    for (int i = 2; i < n; i++) ensuref(parent[i - 1] <= parent[i], "Parent array not nondecreasing at %d", i);

    return parent;
}

static vector<int> makeLengthsCorner(int seed, int& nOut) {
    if (seed == 1) {
        nOut = 4;
        
        return {2, 1};
    }
    if (seed == 2) {
        nOut = 6;
        
        
        return {2, 1, 1, 1};
    }
    
    nOut = 10000;
    
    
    int m = 5000;
    vector<int> len(m, 2);
    len[m - 1] = 1;
    return len;
}

static vector<int> makeLengthsPattern0(int n) {
    
    int mLo = max(2, n / 3);
    int mHi = max(2, n / 2);
    int m = rnd.next(mLo, mHi);
    m = min(m, n - 2);

    vector<int> len(m, 1);

    
    int wantTwo = rnd.next(max(1, m / 3), m);
    vector<int> idx(m);
    iota(idx.begin(), idx.end(), 0);
    
    for (int i = m - 1; i > 0; i--) {
        int j = rnd.next(0, i);
        swap(idx[i], idx[j]);
    }
    for (int k = 0; k < wantTwo; k++) len[idx[k]] = 2;

    
    len[0] = max(len[0], 2);

    long long sum = 0;
    for (int x : len) sum += x;
    long long need = (long long)(n - 1) - sum;

    
    if (need > 0) {
        int tails = rnd.next(1, min(12, m));
        vector<int> tailIdx;
        tailIdx.reserve(tails);
        for (int i = 0; i < tails; i++) tailIdx.push_back(rnd.next(0, m - 1));
        for (int i = 0; i < (int)tailIdx.size() && need > 0; i++) {
            int ci = tailIdx[i];
            int add = (int)min<long long>(need, rnd.next(100, 800));
            len[ci] += add;
            need -= add;
        }
        if (need > 0) {
            len[0] += (int)need;
            need = 0;
        }
    } else if (need < 0) {
        long long over = -need;
        
        for (int i = m - 1; i >= 0 && over > 0; i--) {
            int minLen = (i == 0 ? 2 : 1);
            while (len[i] > minLen && over > 0) {
                len[i]--;
                over--;
            }
        }
        ensuref(over == 0, "Pattern0 adjustment failed: could not reduce enough");
    }

    
    long long finalSum = 0;
    for (int x : len) finalSum += x;
    ensuref(finalSum == n - 1, "Pattern0 sum mismatch %lld vs %d", finalSum, n - 1);
    ensuref(len[0] >= 2, "Pattern0 len[0] must be >=2");
    return len;
}

static vector<int> makeLengthsPattern1(int n) {
    
    int m = rnd.next(5, 30);
    m = min(m, n - 2);
    vector<int> len(m, 1);

    
    long long remaining = (long long)(n - 1) - m;
    for (int i = 1; i < m && remaining > 0; i++) {
        int add = (int)min<long long>(remaining, rnd.next(1, 300));
        len[i] += add;
        remaining -= add;
    }
    
    len[0] = 2;
    remaining -= 1; 
    if (remaining < 0) remaining = 0;
    len[0] += (int)remaining;

    long long finalSum = 0;
    for (int x : len) finalSum += x;
    ensuref(finalSum == n - 1, "Pattern1 sum mismatch %lld vs %d", finalSum, n - 1);
    ensuref(len[0] >= 2, "Pattern1 len[0] must be >=2");
    return len;
}

static vector<int> makeLengthsPattern2(int n) {
    
    int m = rnd.next(80, 220);
    m = min(m, n - 2);
    vector<int> len(m, 1);

    int period = rnd.next(7, 19);
    int peak = rnd.next(30, 160);

    for (int i = 0; i < m; i++) {
        int pos = i % period;
        int target = max(1, peak - pos * (peak / period));
        len[i] += rnd.next(0, max(0, target - 1));
    }

    len[0] = max(len[0], 2);

    long long sum = 0;
    for (int x : len) sum += x;
    long long need = (long long)(n - 1) - sum;

    if (need > 0) {
        
        int i = 0;
        while (need > 0) {
            int add = (int)min<long long>(need, (i < m / 3 ? rnd.next(5, 200) : rnd.next(1, 20)));
            len[i] += add;
            need -= add;
            i++;
            if (i == m) i = 0;
        }
    } else if (need < 0) {
        long long over = -need;
        for (int i = m - 1; i >= 0 && over > 0; i--) {
            int minLen = (i == 0 ? 2 : 1);
            while (len[i] > minLen && over > 0) {
                len[i]--;
                over--;
            }
        }
        ensuref(over == 0, "Pattern2 adjustment failed: could not reduce enough");
    }

    long long finalSum = 0;
    for (int x : len) finalSum += x;
    ensuref(finalSum == n - 1, "Pattern2 sum mismatch %lld vs %d", finalSum, n - 1);
    ensuref(len[0] >= 2, "Pattern2 len[0] must be >=2");
    return len;
}

int main(int argc, char** argv) {
    registerGen(argc, argv, 1);
    string mode = opt<string>("mode", "non");

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

    int nOpt = opt<int>("n", -1);
    int patternOpt = opt<int>("pattern", -1);

    int n = -1;
    vector<int> len;

    if (seed >= 1 && seed <= 3) {
        len = makeLengthsCorner((int)seed, n);
    } else {
        if (nOpt != -1) n = nOpt;
        else n = rnd.next(9500, 10000);
        n = max(n, 4);
        n = min(n, 10000);

        int pattern = patternOpt;
        if (pattern == -1) pattern = (int)(seed % 3);

        if (pattern == 0) len = makeLengthsPattern0(n);
        else if (pattern == 1) len = makeLengthsPattern1(n);
        else len = makeLengthsPattern2(n);
    }

    
    cout << 1 << "\n";
    cout << n << "\n";

    if (mode == "non") {
        vector<int> parent = buildParentsFromChainLengths(n, len);
        for (int i = 1; i < n; i++) {
            if (i > 1) cout << ' ';
            cout << parent[i];
        }
        cout << "\n";
    } else if (mode == "adp") {
        
        
    } else {
        quitf(_fail, "Unknown --mode=%s (expected non or adp)", mode.c_str());
    }

    return 0;
}