Problem: cf1918_e
Difficulty: medium
Categories: data structures, search
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem!

In the new round, there were $n$ tasks with difficulties from $1$ to $n$. The coordinator, who decided to have the first round with tasks in unsorted order of difficulty, rearranged the tasks, resulting in a permutation of difficulties from $1$ to $n$. After that, the coordinator challenged ace5 to guess the permutation in the following way.

Initially, the coordinator chooses a number $x$ from $1$ to $n$.

ace5 can make queries of the form: $?\ i$. The answer will be:

* $>$, if $a_i > x$, after which $x$ increases by $1$.
* $<$, if $a_i < x$, after which $x$ decreases by $1$.
* $=$, if $a_i = x$, after which $x$ remains unchanged.

The task for ace5 is to guess the permutation in no more than $40n$ queries. Since ace5 is too busy writing the announcement, he has entrusted this task to you.

Input

The first line contains a single integer $t$ ($1 \leq t \leq 1000$) — the number of test cases.

Interaction

The interaction between your program and the jury's program begins with reading a positive integer $n$ ($1 \leq n \leq 2000$) — the length of the hidden permutation.

To make a query, output a line in the format "? i", where $1 \leq i \leq n$.

As an answer, you will receive:

* ">", if $a_i$ > $x$, after which $x$ will increase by $1$.
* "<", if $a_i$ < $x$, after which $x$ will decrease by $1$.
* "=", if $a_i$ = $x$, after which $x$ will remain unchanged.

You can make no more than $40n$ queries. To output the answer, you need to print "! a\_1 a\_2 ... a\_n", where $1 \leq a_i \leq n$, and all of them are distinct. Outputting the answer does not count as a query.

If your program makes more than $40n$ queries for one test case, or makes an invalid query, then the response to the query will be -1. 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 print a newline and flush the output buffer. Otherwise, you will receive the verdict Presentation Error. To flush the buffer, 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.

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

The interactor in this problem is not adaptive.

Example

Input

```
2
5

>

=

<

=

<

<

2

>
```

Output

```
? 4

? 2

? 1

? 5

? 1

? 3

! 2 4 1 5 3

? 1

! 2 1
```

Note

In the first test, the hidden permutation is $a$ = [$2,4,1,5,3$], and the initial value of $x$ is $3$.

In the second test, the hidden permutation is $a$ = [$2,1$], and the initial value of $x$ is $1$.

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& tok) {
    tok.clear();
    if (!(cin >> tok)) 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[0] == '+' || s[0] == '-') {
        neg = (s[0] == '-');
        i = 1;
        if (i == (int)s.size()) return false;
    }
    long long val = 0;
    for (; i < (int)s.size(); i++) {
        char c = s[i];
        if (c < '0' || c > '9') return false;
        int d = c - '0';
        if (val > (LLONG_MAX - d) / 10) return false;
        val = val * 10 + d;
    }
    out = neg ? -val : val;
    return true;
}

static long long mustReadIntInRange(long long lo, long long hi, const string& what) {
    string tok;
    if (!readToken(tok)) finish(_pe, "unexpected EOF while reading " + what);
    long long v;
    if (!parseLL(tok, v)) finish(_pe, "invalid integer token for " + what);
    if (v < lo || v > hi) finish(_pe, "integer out of range for " + what);
    return v;
}

struct TestCase {
    int n = 0;
    vector<int> a;
    int x0 = 0;
};

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

    vector<TestCase> cases;
    int t = 0;

    try {
        t = inf.readInt(1, 1000, "t");
        cases.resize(t);
        long long totalBudget = 0;

        for (int tc = 0; tc < t; tc++) {
            int n = inf.readInt(1, 2000, "n");
            vector<int> a(n);
            vector<int> seen(n + 1, 0);
            for (int i = 0; i < n; i++) {
                a[i] = inf.readInt(1, n, "a[i]");
                if (seen[a[i]]++) finish(_fail, "invalid hidden input: not a permutation");
            }
            int x = inf.readInt(1, n, "x");
            cases[tc] = TestCase{n, std::move(a), x};
            totalBudget += 40LL * n;
        }

        query_limit = totalBudget;
        log_metrics(); 

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

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

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

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

            while (true) {
                if (queries > hard_cap) finish(_pe, "hard cap exceeded");

                string cmd;
                if (!readToken(cmd)) finish(_pe, "unexpected EOF: contestant did not output final answer");

                if (cmd == "?") {
                    long long idx = mustReadIntInRange(1, n, "query index");
                    int ai = a[(int)idx - 1];

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

                    if (ai > x) {
                        cout << ">\n";
                        cout.flush();
                        x++;
                    } else if (ai < x) {
                        cout << "<\n";
                        cout.flush();
                        x--;
                    } else {
                        cout << "=\n";
                        cout.flush();
                    }
                } else if (cmd == "!") {
                    vector<int> ans(n);
                    vector<int> used(n + 1, 0);
                    for (int i = 0; i < n; i++) {
                        long long v = mustReadIntInRange(1, n, "answer value");
                        ans[i] = (int)v;
                        if (used[ans[i]]++) finish(_wa, "answer is not a permutation");
                    }
                    if (ans != a) finish(_wa, "wrong permutation");
                    break; 
                } else {
                    finish(_pe, "invalid command token");
                }
            }
        }

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

        finish(_ok, "ok");
    } catch (const std::exception& e) {
        finish(_pe, string("exception: ") + e.what());
    } catch (...) {
        finish(_pe, "unknown exception");
    }
}


Adaptive interactor (C++):

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

static int clampInt(int v, int lo, int hi) {
    if (v < lo) return lo;
    if (v > hi) return hi;
    return v;
}

static vector<int> permZigzag(int n) {
    vector<int> p;
    p.reserve(n);
    int lo = 1, hi = n;
    while ((int)p.size() < n) {
        if ((int)p.size() < n) p.push_back(lo++);
        if ((int)p.size() < n) p.push_back(hi--);
    }
    return p;
}

static vector<int> permBlocks(int n, int blockSize, bool alternateReverse) {
    vector<int> p(n);
    iota(p.begin(), p.end(), 1);
    for (int start = 0, blk = 0; start < n; start += blockSize, blk++) {
        int end = min(n, start + blockSize);
        if (!alternateReverse || (blk % 2 == 1)) {
            reverse(p.begin() + start, p.begin() + end);
        }
    }
    return p;
}

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

static void applySwaps(vector<int>& p, int swaps) {
    int n = (int)p.size();
    for (int k = 0; k < swaps; k++) {
        int i = rnd.next(0, n - 1);
        int j = rnd.next(0, n - 1);
        if (i != j) swap(p[i], p[j]);
    }
}

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

    string mode = opt<string>("mode", "non");
    int nOpt = opt<int>("n", 2000);
    int xOpt = opt<int>("x", -1);
    string pattern = opt<string>("pattern", "mix");

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

    int n = clampInt(nOpt, 1, 2000);
    int x = (xOpt == -1 ? -1 : clampInt(xOpt, 1, n));

    
    cout << 1 << "\n";

    
    if (seedVal == 1) {
        n = 1;
        if (x == -1) x = 1;
        if (mode == "adp") {
            cout << n << "\n" << x << "\n";
        } else {
            cout << n << "\n";
            cout << 1 << "\n";
            cout << x << "\n";
        }
        return 0;
    }
    if (seedVal == 2) {
        n = 2;
        if (x == -1) x = 1;
        if (mode == "adp") {
            cout << n << "\n" << x << "\n";
        } else {
            cout << n << "\n";
            cout << 2 << " " << 1 << "\n";
            cout << x << "\n";
        }
        return 0;
    }
    if (seedVal == 3) {
        n = 2000;
        if (x == -1) x = 1000;
        if (mode == "adp") {
            cout << n << "\n" << x << "\n";
        } else {
            vector<int> p = permZigzag(n);
            cout << n << "\n";
            for (int i = 0; i < n; i++) {
                if (i) cout << ' ';
                cout << p[i];
            }
            cout << "\n" << x << "\n";
        }
        return 0;
    }

    
    n = 2000;
    if (x == -1) {
        int center = n / 2;
        int delta = rnd.next(-n / 6, n / 6);
        x = clampInt(center + delta, 1, n);
        if (rnd.next(1, 20) == 1) x = 1;
        if (rnd.next(1, 20) == 1) x = n;
    }

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

    vector<int> p;
    if (pattern == "zigzag") {
        p = permZigzag(n);
        int rot = rnd.next(0, n - 1);
        rotate(p.begin(), p.begin() + rot, p.end());
        applySwaps(p, rnd.next(n / 2, n));
    } else if (pattern == "blocks") {
        int b = rnd.next(25, 80);
        p = permBlocks(n, b, true);
        int rot = rnd.next(0, n - 1);
        rotate(p.begin(), p.begin() + rot, p.end());
        applySwaps(p, rnd.next(n / 2, 2 * n));
    } else if (pattern == "random") {
        p.resize(n);
        iota(p.begin(), p.end(), 1);
        fisherYates(p);
    } else { 
        int type = rnd.next(0, 2);
        if (type == 0) {
            p = permZigzag(n);
            int rot = rnd.next(0, n - 1);
            rotate(p.begin(), p.begin() + rot, p.end());
            applySwaps(p, rnd.next(n, 2 * n));
        } else if (type == 1) {
            int b = rnd.next(20, 100);
            p = permBlocks(n, b, true);
            int rot = rnd.next(0, n - 1);
            rotate(p.begin(), p.begin() + rot, p.end());
            applySwaps(p, rnd.next(n, 3 * n / 2));
        } else {
            p.resize(n);
            iota(p.begin(), p.end(), 1);
            fisherYates(p);
            
            applySwaps(p, rnd.next(n / 2, 2 * n));
        }
    }

    
    cout << n << "\n";
    for (int i = 0; i < n; i++) {
        if (i) cout << ' ';
        cout << p[i];
    }
    cout << "\n";
    cout << x << "\n";
    return 0;
}