Problem: cf1979_f
Difficulty: medium
Categories: graph, search
Time limit: 3000 ms, memory limit: 256 MB

This is an interactive problem.

Kostyanych has chosen a complete undirected graph$^{\dagger}$ with $n$ vertices, and then removed exactly $(n - 2)$ edges from it. You can ask queries of the following type:

* "? $d$" — Kostyanych tells you the number of vertex $v$ with a degree at least $d$. Among all possible such vertices, he selects the vertex with the minimum degree, and if there are several such vertices, he selects the one with the minimum number. He also tells you the number of another vertex in the graph, with which $v$ is not connected by an edge (if none is found, then $0$ is reported). Among all possible such vertices, he selects the one with the minimum number. Then he removes the vertex $v$ and all edges coming out of it. If the required vertex $v$ is not found, then "$0\ 0$" is reported.

Find a Hamiltonian path$^{\ddagger}$ in the original graph in at most $n$ queries. It can be proven that under these constraints, a Hamiltonian path always exists.

$^{\dagger}$A complete undirected graph is a graph in which there is exactly one undirected edge between any pair of distinct vertices. Thus, a complete undirected graph with $n$ vertices contains $\frac{n(n-1)}{2}$ edges.

$^{\ddagger}$A Hamiltonian path in a graph is a path that passes through each vertex exactly once.

Input

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

The only line of each test case contains a single integer $n$ ($2 \le n \le 10^5$) — the number of vertices in the graph.

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

Interaction

Interaction for each test case begins with reading the integer $n$.

Then you can make no more than $n$ queries.

To make a query, output a line in the format "? $d$" (without quotes) ($0 \le d \le n - 1$). After each query, read two integers — the answer to your query.

When you are ready to report the answer, output a line in the format "! $v_1\ v_2 \ldots v_n$" (without quotes) — the vertices in the order of their occurrence in the Hamiltonian path. Outputting the answer does not count as one of the $n$ queries. 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.

If your program makes more than $n$ queries for one test case or makes an incorrect query, then the response to the query will be $-1$, and after receiving such a response, your program should immediately terminate to receive the verdict Wrong answer. Otherwise, it may receive any other verdict.

After outputting a query, do not forget to output an end of line and flush the output buffer. Otherwise, you will receive the verdict 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 graph does not change during the interaction.

Example

Input

```
3
4

0 0

1 4

2 3

4

1 0

4 2

2

1 0
```

Output

```
? 3

? 2

? 1

! 4 3 1 2

? 3

? 0

! 4 1 2 3

? 0

! 2 1
```

Note

In the first test case, the original graph looks as follows:

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

Consider the queries:

* There are no vertices with a degree of at least $3$ in the graph, so "$0\ 0$" is reported.
* There are four vertices with a degree of at least $2$, and all of them have a degree of exactly $2$: $1$, $2$, $3$, $4$. Vertex $1$ is reported, because it has the minimum number, and vertex $4$ is reported, because it is the only one not connected to vertex $1$. After this, vertex $1$ is removed from the graph.
* There are three vertices with a degree of at least $1$, among them vertices $2$ and $3$ have a minimum degree of $1$ (vertex $4$ has a degree of $2$). Vertex $2$ is reported, because it has the minimum number, and vertex $3$ is reported, because it is the only one not connected to vertex $2$. After this, vertex $2$ is removed from the graph.

The path $4 - 3 - 1 - 2$ is a Hamiltonian path.

In the second test case, the original graph looks as follows:

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

Consider the queries:

* Vertex $1$ has a degree of at least $3$, but it is connected to all vertices, so "$1\ 0$" is reported. After this, vertex $1$ is removed from the graph.
* The remaining vertices $2$, $3$, and $4$ have a degree of at least $0$, but among them vertex $4$ has the minimum degree of $0$ (vertices $2$ and $3$ have a degree of $1$). Vertex $4$ is not connected to both vertices $2$ and $3$, so vertex $2$ is reported (as it has the minimum number). After this, vertex $4$ is removed from the graph.

The path $4 - 1 - 2 - 3$ is a Hamiltonian path.

In the third test case, the graph consists of $2$ vertices connected by an edge.

Non-adaptive interactor (C++):























#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;


static long long global_queries = 0;
static long long global_query_limit = 0;


void log_metrics() {
    try {
        tout << "queries=" << global_queries << endl;
        tout << "query_limit=" << global_query_limit << endl;
    } catch (...) {
        
    }
}


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


int n;
vector<vector<int>> adj_comp;  
vector<int> deg_comp;          
vector<bool> active;           
int current_n;                 
set<int> present_degrees;      
vector<set<int>> buckets;      
set<pair<int,int>> complement_edges; 

void solve_testcase() {
    
    n = inf.readInt();
    
    
    cout << n << endl;

    
    global_query_limit += n;
    
    log_metrics();

    
    current_n = n;
    adj_comp.assign(n + 1, vector<int>());
    deg_comp.assign(n + 1, 0);
    active.assign(n + 1, true);
    
    buckets.assign(n + 1, set<int>());
    present_degrees.clear();
    complement_edges.clear();

    
    int m = n - 2;
    for (int i = 0; i < m; ++i) {
        int u = inf.readInt();
        int v = inf.readInt();
        if (u > v) swap(u, v);
        
        complement_edges.insert({u, v});
        adj_comp[u].push_back(v);
        adj_comp[v].push_back(u);
        deg_comp[u]++;
        deg_comp[v]++;
    }

    
    for (int i = 1; i <= n; ++i) {
        sort(adj_comp[i].begin(), adj_comp[i].end()); 
        buckets[deg_comp[i]].insert(i);
        present_degrees.insert(deg_comp[i]);
    }

    int queries_this_case = 0;

    
    while (true) {
        string token;
        cin >> token;
        
        if (cin.fail()) {
            finish(_pe, "Unexpected end of input from solution");
        }

        if (token == "!") {
            
            vector<int> path;
            path.reserve(n);
            vector<bool> visited(n + 1, false);
            
            for (int i = 0; i < n; ++i) {
                int v_node;
                cin >> v_node;
                if (cin.fail()) finish(_pe, "Failed to read path vertex");
                path.push_back(v_node);
            }

            
            for (int x : path) {
                if (x < 1 || x > n) finish(_wa, "Vertex in path out of range");
                if (visited[x]) finish(_wa, "Duplicate vertex in path");
                visited[x] = true;
            }

            
            for (int i = 0; i < n - 1; ++i) {
                int u = path[i];
                int v = path[i+1];
                if (u > v) swap(u, v);
                if (complement_edges.count({u, v})) {
                    finish(_wa, format("Edge %d-%d is missing in the graph (it is in the removed set)", path[i], path[i+1]));
                }
            }

            
            break; 
        } 
        else {
            
            int d;
            if (token == "?") {
                
                cin >> d;
            } else {
                
                try {
                    size_t pos;
                    d = stoi(token, &pos);
                    if (pos != token.size()) throw invalid_argument("");
                } catch (...) {
                    finish(_pe, format("Invalid query format: unexpected token '%s'", token.c_str()));
                }
            }
            if (cin.fail()) finish(_pe, "Failed to read query parameter d");

            queries_this_case++;
            global_queries++;
            
            
            if (global_queries > 500000) {
                 finish(_pe, "Global hard query limit exceeded");
            }

            
            if (queries_this_case > n) {
                cout << -1 << endl;
                finish(_wa, "Query limit exceeded for test case");
            }

            
            if (d < 0 || d >= n) {
                cout << -1 << endl;
                finish(_wa, format("Query parameter d=%d out of range [0, %d]", d, n-1));
            }

            
            
            
            
            int K = (current_n - 1) - d;
            int v_res = 0;
            int u_res = 0;

            if (K >= 0) {
                
                
                
                
                auto it = present_degrees.upper_bound(K);
                if (it != present_degrees.begin()) {
                    it--; 
                    int k = *it;
                    
                    if (!buckets[k].empty()) {
                        
                        v_res = *buckets[k].begin();
                        
                        
                        
                        
                        
                        for (int neighbor : adj_comp[v_res]) {
                            if (active[neighbor]) {
                                u_res = neighbor;
                                break; 
                            }
                        }
                    }
                }
            }

            
            cout << v_res << " " << u_res << endl;

            
            if (v_res != 0) {
                
                active[v_res] = false;
                current_n--;

                
                int old_d = deg_comp[v_res];
                buckets[old_d].erase(v_res);
                if (buckets[old_d].empty()) present_degrees.erase(old_d);

                
                
                for (int w : adj_comp[v_res]) {
                    if (active[w]) {
                        int w_d = deg_comp[w];
                        buckets[w_d].erase(w);
                        if (buckets[w_d].empty()) present_degrees.erase(w_d);

                        deg_comp[w]--;
                        w_d = deg_comp[w];
                        buckets[w_d].insert(w);
                        present_degrees.insert(w_d);
                    }
                }
            }
        }
    }
}

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

    int t = inf.readInt();
    cout << t << endl;

    for (int i = 0; i < t; ++i) {
        solve_testcase();
    }

    finish(_ok, "All test cases passed");
    return 0;
}


Adaptive interactor (C++):

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

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

    
    string mode = opt<string>("mode", "non");

    
    
    
    const int MAX_TOTAL_N = 100000;
    const int MAX_T = 1000;

    
    int target_n = rnd.next(MAX_TOTAL_N / 2, MAX_TOTAL_N);

    vector<int> cases;
    
    cases.push_back(2);
    cases.push_back(3);
    cases.push_back(4);
    cases.push_back(4);
    cases.push_back(5);

    int current_n = 0;
    for (int x : cases) current_n += x;

    
    while (current_n < target_n && (int)cases.size() < MAX_T) {
        int rem = target_n - current_n;
        if (rem < 2) break;

        
        int type = rnd.next(100);
        int n;

        if (type < 40) { 
            n = rnd.next(2, min(rem, 50));
        } else if (type < 80) { 
            n = rnd.next(min(rem, 51), min(rem, 1000));
        } else { 
            n = rnd.next(min(rem, 1001), min(rem, 5000));
        }

        
        if (n < 2) n = 2; 
        if (n > rem) n = rem;

        cases.push_back(n);
        current_n += n;
    }

    
    shuffle(cases.begin(), cases.end());

    
    println(cases.size());

    for (int n : cases) {
        println(n);

        
        if (mode == "adp") {
            continue;
        }

        
        int m = n - 2;
        vector<pair<int, int>> edges;

        
        
        
        
        
        
        
        int gtype = rnd.next(5);
        if (n < 5) gtype = 0; 

        if (gtype == 0) {
            
            set<pair<int, int>> s;
            while ((int)s.size() < m) {
                int u = rnd.next(1, n);
                int v = rnd.next(1, n);
                if (u == v) continue;
                if (u > v) swap(u, v);
                s.insert({u, v});
            }
            for (auto p : s) edges.push_back(p);
        }
        else if (gtype == 1) {
            
            int c = rnd.next(1, n);
            vector<int> nodes;
            for (int i = 1; i <= n; ++i) if (i != c) nodes.push_back(i);
            shuffle(nodes.begin(), nodes.end());
            
            for (int i = 0; i < m; ++i) {
                int u = c, v = nodes[i];
                if (u > v) swap(u, v);
                edges.push_back({u, v});
            }
        }
        else if (gtype == 2) {
            
            vector<int> p(n);
            iota(p.begin(), p.end(), 1);
            shuffle(p.begin(), p.end());
            
            for (int i = 0; i < m; ++i) {
                int u = p[i], v = p[i + 1];
                if (u > v) swap(u, v);
                edges.push_back({u, v});
            }
        }
        else if (gtype == 3) {
            
            set<pair<int, int>> s;
            vector<int> p(n);
            iota(p.begin(), p.end(), 1);
            shuffle(p.begin(), p.end());
            
            for (int i = 0; i + 1 < n && (int)s.size() < m; i += 2) {
                int u = p[i], v = p[i + 1];
                if (u > v) swap(u, v);
                s.insert({u, v});
            }
            
            while ((int)s.size() < m) {
                int u = rnd.next(1, n);
                int v = rnd.next(1, n);
                if (u == v) continue;
                if (u > v) swap(u, v);
                s.insert({u, v});
            }
            for (auto e : s) edges.push_back(e);
        }
        else {
            
            
            vector<int> p(n);
            iota(p.begin(), p.end(), 1);
            shuffle(p.begin(), p.end());
            vector<pair<int, int>> tree_edges;
            
            for (int i = 1; i < n; ++i) {
                int u = p[i];
                int v = p[rnd.next(i)];
                if (u > v) swap(u, v);
                tree_edges.push_back({u, v});
            }
            shuffle(tree_edges.begin(), tree_edges.end());
            for (int i = 0; i < m; ++i) edges.push_back(tree_edges[i]);
        }

        
        shuffle(edges.begin(), edges.end());
        for (auto e : edges) {
            println(e.first, e.second);
        }
    }

    return 0;
}