Problem: cf2066_a
Difficulty: medium
Categories: graph
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem.

You are given an array $x_1, \ldots, x_n$ of integers from $1$ to $n$. The jury also has a fixed but hidden array $y_1, \ldots, y_n$ of integers from $1$ to $n$. The elements of array $y$ are unknown to you. Additionally, it is known that for all $i$, $x_i \neq y_i$, and all pairs $(x_i, y_i)$ are distinct.

The jury has secretly thought of one of two objects, and you need to determine which one it is:

* Object A: A directed graph with $n$ vertices numbered from $1$ to $n$, and with $n$ edges of the form $x_i \to y_i$.
* Object B: $n$ points on a coordinate plane. The $i$-th point has coordinates $(x_i, y_i)$.

To guess which object the jury has thought of, you can make queries. In one query, you must specify two numbers $i, j$ $(1 \leq i, j \leq n, i \neq j)$. In response, you receive one number:

* If the jury has thought of Object A, you receive the length of the shortest path (in edges) from vertex $i$ to vertex $j$ in the graph, or $0$ if there is no path.
* If the jury has thought of Object B, you receive the Manhattan distance between points $i$ and $j$, that is $|x_i -x_j| + |y_i - y_j|$.

You have $2$ queries to determine which of the objects the jury has thought of.

Input

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

Interaction

The interaction begins with reading $n$ ($3 \leq n \leq 2 \cdot 10^5$) — the length of the arrays $x$ and $y$ at the start of each test case.

Next, read $n$ integers: $x_1, x_2, \ldots, x_n$ ($1 \leq x_i \leq n$) — the elements of array $x$.

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

The array $y_1, y_2, \ldots, y_n$ is fixed for each test case. In other words, the interactor is not adaptive.

It is guaranteed that $x_i \neq y_i$ for all $1 \leq i \leq n$, and all pairs $(x_i, y_i)$ are distinct.

To make a query, output "? $i$ $j$" (without quotes, $1 \le i, j \le n, i \neq j$). Then you must read the response to the query, which is a non-negative integer.

To give an answer, output "! A" if Object A is hidden or "! B" if Object B is hidden (without quotes). Note that printing the answer does not count as one of the $2$ queries.

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 reveive 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. Note that if the query is correct, the response will never be $-1$.

Example

Input

```
2
3
2 2 3

1

0

5
5 1 4 2 3

4

4
```

Output

```
? 2 3

? 1 2

! A

? 1 5

? 5 1

! B
```

Note

In the first test case, $x = [2,2,3]$, $y = [1,3,1]$ and Object A is guessed.

In the second test case, $x = [5,1,4,2,3]$, $y = [3,3,2,4,1]$ and Object B is guessed.

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 long long hard_cap = 200000;

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 parsePosIntInRange(const string& s, int& out, int lo, int hi) {
    if (s.empty()) return false;
    long long val = 0;
    for (char c : s) {
        if (c < '0' || c > '9') return false;
        val = val * 10 + (c - '0');
        if (val > (long long)hi) return false;
    }
    if (val < lo || val > hi) return false;
    out = (int)val;
    return true;
}

static void sendMinusOne() {
    cout << -1 << endl;
}

static int shortestPathDirected(int n, const vector<vector<int>>& adj, int s, int t) {
    if (s == t) return 0;
    vector<int> dist(n + 1, -1);
    deque<int> q;
    dist[s] = 0;
    q.push_back(s);
    while (!q.empty()) {
        int u = q.front();
        q.pop_front();
        int nd = dist[u] + 1;
        for (int v : adj[u]) {
            if (dist[v] != -1) continue;
            dist[v] = nd;
            if (v == t) return nd;
            q.push_back(v);
        }
    }
    return 0;
}

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

    int t = 0;
    try {
        t = inf.readInt();
    } catch (...) {
        query_limit = 0;
        log_metrics();
        finish(_pe, "Failed to read t from inf");
    }
    if (t < 1 || t > 1000) {
        query_limit = 0;
        log_metrics();
        finish(_pe, "Invalid t in inf");
    }

    query_limit = 2LL * t;
    hard_cap = max(200000LL, 10LL * query_limit);
    log_metrics(); 

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

    for (int tc = 1; tc <= t; tc++) {
        int n = inf.readInt();
        if (n < 3 || n > 200000) finish(_pe, "Invalid n in inf");

        vector<int> x(n + 1), y(n + 1);
        for (int i = 1; i <= n; i++) {
            x[i] = inf.readInt(1, n);
        }
        for (int i = 1; i <= n; i++) {
            y[i] = inf.readInt(1, n);
        }

        string objTok = inf.readToken();
        if (objTok.empty()) finish(_pe, "Missing object token in inf");
        char obj = (char)toupper((unsigned char)objTok[0]);
        if (obj != 'A' && obj != 'B') finish(_pe, "Invalid object token in inf");

        vector<vector<int>> adj;
        if (obj == 'A') {
            adj.assign(n + 1, {});
            for (int i = 1; i <= n; i++) adj[x[i]].push_back(y[i]);
        }

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

        bool answered = false;
        while (!answered) {
            string cmd;
            if (!readToken(cmd)) finish(_pe, "EOF from contestant before answering");

            if (cmd == "?") {
                string si, sj;
                if (!readToken(si) || !readToken(sj)) {
                    sendMinusOne();
                    cout.flush();
                    finish(_pe, "Malformed query: missing i/j");
                }

                int i = 0, j = 0;
                if (!parsePosIntInRange(si, i, 1, n) || !parsePosIntInRange(sj, j, 1, n) || i == j) {
                    sendMinusOne();
                    cout.flush();
                    finish(_pe, "Invalid query indices");
                }

                queries++;
                if (queries > hard_cap) {
                    sendMinusOne();
                    cout.flush();
                    finish(_pe, "Hard cap exceeded");
                }

                long long ans = 0;
                if (obj == 'B') {
                    ans = llabs((long long)x[i] - x[j]) + llabs((long long)y[i] - y[j]);
                } else {
                    ans = shortestPathDirected(n, adj, i, j);
                }

                cout << ans << '\n';
                cout.flush();
            } else if (cmd == "!") {
                string guessTok;
                if (!readToken(guessTok) || guessTok.empty()) {
                    sendMinusOne();
                    cout.flush();
                    finish(_pe, "Malformed answer: missing A/B");
                }
                char g = (char)toupper((unsigned char)guessTok[0]);
                if (g != 'A' && g != 'B') {
                    sendMinusOne();
                    cout.flush();
                    finish(_pe, "Malformed answer: not A/B");
                }
                if (g != obj) finish(_wa, "Wrong object guessed");
                answered = true;
            } else {
                sendMinusOne();
                cout.flush();
                finish(_pe, "Unexpected command token");
            }
        }
    }

    string extra;
    if (readToken(extra)) finish(_pe, "Extra output after finishing all testcases");
    finish(_ok, "OK");
}


Adaptive interactor (C++):

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

static vector<int> randomPermutation(int n) {
    vector<int> p(n);
    iota(p.begin(), p.end(), 1);
    for (int i = 0; i < n; i++) {
        int j = rnd.next(i, n - 1);
        swap(p[i], p[j]);
    }
    return p;
}

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

    string mode = opt<string>("mode", "non"); 
    int nDefault = opt<int>("n", 200000);
    string objOpt = opt<string>("obj", ""); 

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

    char obj;
    if (!objOpt.empty()) {
        obj = objOpt[0];
        if (obj != 'A' && obj != 'B') obj = 'A';
    } else {
        obj = (seed % 2 ? 'A' : 'B');
    }

    int n = nDefault;
    if (n < 3) n = 3;
    if (n > 200000) n = 200000;

    vector<int> x, y;

    if (seed == 1) {
        n = 3;
        x = {1, 2, 3};
        y = {2, 3, 1};
        obj = 'A';
    } else if (seed == 2) {
        n = 3;
        x = {1, 1, 2};
        y = {2, 3, 3}; 
        obj = 'A';
    } else if (seed == 3) {
        n = 5;
        x = {1, 2, 3, 4, 5};
        y = {2, 1, 4, 5, 3}; 
        obj = 'B';
    } else {
        
        n = nDefault;
        if (n < 3) n = 3;
        if (n > 200000) n = 200000;

        x = randomPermutation(n);

        vector<int> cycle = randomPermutation(n);
        vector<int> f(n + 1, 0);
        for (int i = 0; i < n; i++) {
            int u = cycle[i];
            int v = cycle[(i + 1) % n];
            f[u] = v;
        }

        y.resize(n);
        for (int i = 0; i < n; i++) {
            y[i] = f[x[i]];
        }
    }

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

    if (mode == "non") {
        for (int i = 0; i < n; i++) {
            if (i) cout << ' ';
            cout << y[i];
        }
        cout << "\n";
        cout << obj << "\n";
    } else if (mode == "adp") {
        
        cout << obj << "\n";
    } else {
        
        for (int i = 0; i < n; i++) {
            if (i) cout << ' ';
            cout << y[i];
        }
        cout << "\n";
        cout << obj << "\n";
    }

    return 0;
}