Problem: cf2150_e2
Difficulty: hard
Categories: search
Time limit: 5000 ms, memory limit: 256 MB

AdhesiveWombat - Overdrive

⠀

The two versions have different constraints on $t$, $n$, and the maximum number of queries, and solving one of the two versions does not necessarily solve the other. You may want to read both versions.

This is an interactive problem.

There is a hidden array $a_1, a_2, \ldots, a_{2n-1}$ containing all the numbers from $1$ to $n$, and all of them appear twice except one (which only appears once).

You can ask queries in the following format, where $S$ is a subset of $\{1, 2, \ldots, 2n-1\}$ and $x$ is an integer in $[1, n]$:

* $\texttt{ask(S, x)}$: does there exist $i \in S$ such that $a_i = x$?

Find the number appearing exactly once, using at most $925$ queries. You don't need to find its position.

Note that the interactor is not adaptive, which means that the hidden array does not depend on the queries you make.

Input

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

The first line of each test case contains a single integer $n$ ($n = 300$) — the maximum value in the hidden array $a_1, a_2, \ldots, a_{2n-1}$.

There are exactly $50$ tests in this problem (including the example). The example has $t = 1$, and all the other tests have $t = 20$.

Interaction

For each test case, first read a single integer $n$. If the integer you read is $-1$, it means that the answer to the previous test case was wrong, and you should exit immediately.

You may ask up to $925$ queries in each test case.

To ask a query, print a line in the format $\texttt{? x |S| S_1 S_2... S_|S|}$ with $1 \leq x \leq n$, $1 \leq S_1, S_2, \ldots, S_{|S|} \leq 2n-1$, and all the $S_i$ distinct.

As a response to the query, you will get $1$ if the answer is yes, $0$ if the answer is no, and $-1$ if you made an invalid query. You should exit immediately if you receive a $-1$.

To output an answer, you should print $\texttt{! y}$, where $y$ is the number that appears exactly once. Printing the answer doesn't count as a query.

See the interaction example for more clarity.

If you ask too many queries, you ask a malformed query, or your answer is wrong, you will get $\texttt{Wrong answer}$.

After printing a query, do not forget to output the end of line and flush the output. Otherwise, you will get $\texttt{Idleness limit exceeded}$. To do this, use:

* $\texttt{fflush(stdout)}$ or $\texttt{cout.flush()}$ in C++;
* $\texttt{System.out.flush()}$ in Java;
* $\texttt{flush(output)}$ in Pascal;
* $\texttt{stdout.flush()}$ in Python;
* see the documentation for other languages.

Note that the interactor is not adaptive, which means that the hidden arrays do not depend on the queries you make.

Example

Input

```
1
300

0
```

Output

```? 187 1 1! 187
```

Note

In the first test case, $n = 300$, so the hidden array has length $2n-1 = 599$.

|  |  |  |  |
| --- | --- | --- | --- |
| # | Contestant prints | Interactor replies | Explanation |
| 1 |? 187 1 1 | 0 | Query: does $a_1=187$? No. |
| 2 |! 187 |  | We feel lucky, and claim that the answer is $187$. Fortunately, the answer is correct. |

We have asked $1$ query (printing the answer does not count as a query), which is less than the maximum allowed number of queries ($925$).

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 bool readLL(long long& out) {
    if (!(cin >> out)) return false;
    return true;
}

static bool readToken(string& out) {
    if (!(cin >> out)) return false;
    return true;
}

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

    int t = 0;
    if (inf.seekEof()) finish(_pe, "Empty input");
    t = inf.readInt(1, 1000000, "t");

    const long long per_case_budget = 925;
    query_limit = per_case_budget * 1LL * t;

    
    log_metrics();

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

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

    for (int tc = 1; tc <= t; ++tc) {
        int n = inf.readInt(1, 1000000000, "n");
        int m = 2 * n - 1;

        vector<int> a(m + 1, 0);
        vector<int> cnt(n + 1, 0);
        for (int i = 1; i <= m; ++i) {
            int v = inf.readInt(1, n, "a[i]");
            a[i] = v;
            cnt[v]++;
        }

        int singleton = -1;
        for (int x = 1; x <= n; ++x) {
            if (cnt[x] == 1) {
                if (singleton != -1) finish(_pe, "Invalid hidden input: multiple singletons");
                singleton = x;
            } else if (cnt[x] != 2) {
                finish(_pe, "Invalid hidden input: value count not 1 or 2");
            }
        }
        if (singleton == -1) finish(_pe, "Invalid hidden input: no singleton");

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

        while (true) {
            if (queries > hard_cap) finish(_pe, "Hard cap exceeded (possible infinite loop/output spam)");

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

            if (cmd == "?") {
                long long x_ll = 0, k_ll = 0;
                if (!readLL(x_ll) || !readLL(k_ll)) {
                    cout << -1 << endl;
                    cout.flush();
                    finish(_pe, "Malformed query header");
                }

                if (x_ll < 1 || x_ll > n || k_ll < 1 || k_ll > m) {
                    cout << -1 << endl;
                    cout.flush();
                    finish(_pe, "Query parameter out of range");
                }

                int x = (int)x_ll;
                int k = (int)k_ll;

                vector<char> seen(m + 1, 0);
                bool ok = true;
                bool exists = false;

                for (int i = 0; i < k; ++i) {
                    long long idx_ll = 0;
                    if (!readLL(idx_ll)) {
                        cout << -1 << endl;
                        cout.flush();
                        finish(_pe, "Malformed query indices");
                    }
                    if (idx_ll < 1 || idx_ll > m) ok = false;
                    else {
                        int idx = (int)idx_ll;
                        if (seen[idx]) ok = false;
                        seen[idx] = 1;
                        if (a[idx] == x) exists = true;
                    }
                }

                if (!ok) {
                    cout << -1 << endl;
                    cout.flush();
                    finish(_pe, "Invalid query indices (range/distinctness)");
                }

                ++queries;
                cout << (exists ? 1 : 0) << endl;
                cout.flush();
            } else if (cmd == "!") {
                long long y_ll = 0;
                if (!readLL(y_ll)) finish(_pe, "Malformed answer");
                if (y_ll < 1 || y_ll > n) finish(_wa, "Answer out of range");
                int y = (int)y_ll;
                if (y != singleton) {
                    
                    cout << -1 << endl;
                    cout.flush();
                    finish(_wa, "Wrong answer");
                }
                break; 
            } else {
                finish(_pe, "Unknown command token");
            }
        }
    }

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


Adaptive interactor (C++):

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

template <class T>
static void fisherYatesShuffle(vector<T>& v) {
    for (int i = (int)v.size() - 1; i > 0; --i) {
        int j = rnd.next(0, i);
        swap(v[i], v[j]);
    }
}

static vector<int> buildNonInstance(int n, int seed, int forcedY) {
    int y;
    if (forcedY != 0) {
        y = forcedY;
    } else if (seed == 1) {
        y = 1;
    } else if (seed == 2) {
        y = n;
    } else if (seed == 3) {
        y = (n + 1) / 2;
    } else {
        y = rnd.next(1, n);
    }

    vector<int> a;
    a.reserve(2 * n - 1);

    if (seed == 1) {
        
        for (int x = 2; x <= n; ++x) {
            a.push_back(x);
            a.push_back(x);
        }
        a.push_back(1);
        return a;
    }

    if (seed == 2) {
        
        for (int x = 1; x <= n; ++x) a.push_back(x);
        for (int x = n - 1; x >= 1; --x) a.push_back(x);
        return a;
    }

    if (seed == 3) {
        
        
        
        vector<int> vals;
        vals.reserve(n - 1);
        for (int x = 1; x <= n; ++x) if (x != y) vals.push_back(x);

        for (int x : vals) a.push_back(x);
        for (int i = (int)vals.size() - 1; i >= 0; --i) a.push_back(vals[i]);
        a.push_back(y);
        return a;
    }

    
    int m = 2 * n - 1;
    vector<int> positions(m);
    iota(positions.begin(), positions.end(), 0);
    fisherYatesShuffle(positions);

    vector<int> lowPos(positions.begin(), positions.begin() + (n - 1));
    vector<int> highPos(positions.begin() + (n - 1), positions.end());
    fisherYatesShuffle(lowPos);
    fisherYatesShuffle(highPos);

    vector<int> vals;
    vals.reserve(n - 1);
    for (int x = 1; x <= n; ++x) if (x != y) vals.push_back(x);
    fisherYatesShuffle(vals);

    vector<int> out(m, 0);
    for (int i = 0; i < n - 1; ++i) {
        out[lowPos[i]] = vals[i];
        out[highPos[i]] = vals[i];
    }
    out[highPos[n - 1]] = y;

    return out;
}

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

    string mode = opt<string>("mode", "non");
    int n = opt<int>("n", 300);
    int forcedY = opt<int>("y", 0);

    if (n < 1) n = 1;
    if (forcedY != 0) {
        if (forcedY < 1) forcedY = 1;
        if (forcedY > n) forcedY = n;
    }

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

    if (mode == "adp") {
        int y;
        if (forcedY != 0) {
            y = forcedY;
        } else if (seed == 1) {
            y = 1;
        } else if (seed == 2) {
            y = n;
        } else if (seed == 3) {
            y = (n + 1) / 2;
        } else {
            y = rnd.next(1, n);
        }

        cout << 1 << "\n";
        cout << n << "\n";
        cout << y << "\n";
        return 0;
    }

    
    vector<int> a = buildNonInstance(n, seed, forcedY);

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