Problem: cf2061_g
Difficulty: hard
Categories: greedy
Time limit: 4000 ms, memory limit: 256 MB

This is an interactive problem.

Kevin has $n$ classmates, numbered $1, 2, \ldots, n$. Any two of them may either be friends or not friends.

Kevin wants to select $2k$ classmates to form $k$ teams, where each team contains exactly $2$ people. Each person can belong to at most one team.

Let $u_i$ and $v_i$ be two people in the $i$-th team. To avoid potential conflicts during team formation, the team members must satisfy one of the following two conditions:

* For all $i$ ($1\leq i \leq k$), classmate $u_i$ and $v_i$ are friends.
* For all $i$ ($1\leq i \leq k$), classmate $u_i$ and $v_i$ are not friends.

Kevin wants to determine the maximum $k$ such that, regardless of the friendship relationships among the $n$ people, he can always find $2k$ people to form the teams. After that, he needs to form $k$ teams. But asking whether two classmates are friends is awkward, so Kevin wants to achieve this while asking about the friendship status of no more than $n$ pairs of classmates.

The interactor is adaptive. It means that the hidden relationship between classmates is not fixed before the interaction and will change during the interaction.

Interaction

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

The first line of each test case contains one positive integer $n$ ($2\leq n \leq 10^5$) — the number of classmates.

First, you should output an integer $k$ ($1\leq k\leq \frac{n}2$) — the maximum number of teams you can form.

You can make queries in the following way — print one line of the form $?\;u\;v$ where $1\leq u\neq v \leq n$. After that, read a single integer: $0$ or $1$ indicating whether they are friends. $1$ means they are friends while $0$ means not.

If you want to print the answer, output $!\;u_1\;v_1\;u_2\;v_2\;\ldots\;u_k\;v_k$. You should output exactly $2k$ distinct numbers. Then, the interaction continues with the next test case.

You can make at most $n$ queries. Printing the answer does not count towards the number of queries made.

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

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.

Example

Input

```
2
3

1

5

1

0

1

0

0
```

Output

```
1
? 1 2

! 1 2

2
? 1 2

? 3 4

? 3 5

? 1 3

? 2 4

! 1 2 3 5
```

Note

In the first test case:

Kevin claims he can form $1$ team regardless of the friendship relationships among the $3$ people.

Kevin asks about the friendship relationship between people $1$ and $2$. The jury responds that they are friends.

Kevin answers that he can form a team with people $1$ and $2$.

In the second test case:

Kevin claims he can form $2$ teams regardless of the friendship relationships among the $5$ people.

Kevin asks about the friendship relationship between people $(1, 2), (3, 4), (3, 5), (1, 3), (2, 4)$. The jury responds with $1, 0, 1, 0, 0$.

Kevin answers that he can form two teams with people $(1, 2)$ and $(3, 5)$.

It is also possible to form two teams with people $(1, 3)$ and $(2, 4)$, since they are both not friends.

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 isDigits(const string& s) {
    if (s.empty()) return false;
    for (char c : s) if (c < '0' || c > '9') return false;
    return true;
}

static long long parseLLNonNeg(const string& s, const string& what) {
    if (!isDigits(s)) finish(_pe, "Malformed integer token for " + what);
    if (s.size() > 19) finish(_pe, "Integer token too long for " + what);
    long long x = 0;
    for (char c : s) {
        int d = c - '0';
        if (x > (LLONG_MAX - d) / 10) finish(_pe, "Integer overflow for " + what);
        x = x * 10 + d;
    }
    return x;
}

static uint64_t splitmix64(uint64_t x) {
    x += 0x9e3779b97f4a7c15ULL;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
    x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
    return x ^ (x >> 31);
}

static int friendship(int u, int v, uint64_t salt) {
    if (u > v) swap(u, v);
    uint64_t x = salt;
    x ^= (uint64_t)u * 0x9e3779b97f4a7c15ULL;
    x ^= (uint64_t)v * 0xbf58476d1ce4e5b9ULL;
    return (int)(splitmix64(x) & 1ULL);
}

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

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

    int t = 0;
    try {
        t = inf.readInt(1, 10000, "t");
    } catch (...) {
        finish(_pe, "Failed to read t from hidden input");
    }

    vector<int> ns(t);
    vector<uint64_t> salts(t);

    long long totalN = 0;
    for (int i = 0; i < t; i++) {
        int n = 0;
        try {
            n = inf.readInt(2, 100000, "n");
        } catch (...) {
            finish(_pe, "Failed to read n from hidden input");
        }
        ns[i] = n;
        totalN += n;

        long long saltSigned = 0;
        try {
            saltSigned = inf.readLong();
        } catch (...) {
            
            saltSigned = 0;
        }
        salts[i] = (uint64_t)saltSigned;
    }

    query_limit = totalN;
    log_metrics(); 

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

    cout << t << endl;

    for (int tc = 0; tc < t; tc++) {
        int n = ns[tc];
        uint64_t salt = salts[tc];

        cout << n << endl;

        string tok;
        if (!readToken(tok)) finish(_pe, "EOF while expecting k");
        long long k = parseLLNonNeg(tok, "k");

        long long kmax = (n + 1) / 3;
        if (k < 1 || k > n / 2) finish(_wa, "k out of allowed range");
        if (k != kmax) finish(_wa, "Incorrect k");

        while (true) {
            string cmd;
            if (!readToken(cmd)) finish(_pe, "EOF while expecting command");

            if (cmd == "?") {
                string su, sv;
                if (!readToken(su) || !readToken(sv)) finish(_pe, "EOF in query");
                long long u = parseLLNonNeg(su, "u");
                long long v = parseLLNonNeg(sv, "v");
                if (u < 1 || u > n || v < 1 || v > n || u == v) finish(_pe, "Invalid query indices");

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

                int ans = friendship((int)u, (int)v, salt);
                cout << ans << endl;
            } else if (cmd == "!") {
                vector<int> a(2 * (size_t)k);
                vector<char> used(n + 1, 0);

                for (long long i = 0; i < 2 * k; i++) {
                    string sx;
                    if (!readToken(sx)) finish(_pe, "EOF in answer");
                    long long x = parseLLNonNeg(sx, "answer vertex");
                    if (x < 1 || x > n) finish(_wa, "Answer vertex out of range");
                    if (used[(int)x]) finish(_wa, "Duplicate vertex in answer");
                    used[(int)x] = 1;
                    a[(size_t)i] = (int)x;
                }

                int base = friendship(a[0], a[1], salt);
                for (long long i = 0; i < k; i++) {
                    int u = a[(size_t)(2 * i)];
                    int v = a[(size_t)(2 * i + 1)];
                    if (u == v) finish(_wa, "Pair has identical vertices");
                    int cur = friendship(u, v, salt);
                    if (cur != base) finish(_wa, "Pairs are not all the same type (friends vs not friends)");
                }
                break;
            } else {
                finish(_pe, "Unknown command token");
            }
        }
    }

    string extra;
    if (readToken(extra)) finish(_pe, "Extra output after finishing all test cases");
    finish(_ok, "OK");
    return 0;
}


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';
    } catch (...) {
        
    }
}

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

static bool isDigits(const string& s) {
    if (s.empty()) return false;
    for (char c : s) if (c < '0' || c > '9') return false;
    return true;
}

static long long parseLLStrict(const string& s, bool& ok) {
    ok = false;
    if (!isDigits(s)) return 0;
    long long x = 0;
    for (char c : s) {
        int d = c - '0';
        if (x > (LLONG_MAX - d) / 10) return 0;
        x = x * 10 + d;
    }
    ok = true;
    return x;
}

static long long readLLFromCin(const char* what) {
    string tok;
    if (!(cin >> tok)) finish(_pe, string("unexpected EOF while reading ") + what);
    bool ok = false;
    long long x = parseLLStrict(tok, ok);
    if (!ok) finish(_pe, string("invalid integer token for ") + what);
    return x;
}

static uint64_t packPair(int u, int v) {
    if (u > v) swap(u, v);
    return (uint64_t)(uint32_t)u << 32 | (uint32_t)v;
}

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

    int t = inf.readInt(1, 10000, "t");
    vector<int> ns(t);
    vector<int> kmax(t);

    long long sumN = 0;
    for (int i = 0; i < t; i++) {
        int n = inf.readInt(2, 100000, "n");
        ns[i] = n;
        sumN += n;
        kmax[i] = (n + 1) / 3;
    }

    query_limit = sumN;
    log_metrics(); 

    cout << t << '\n';
    for (int i = 0; i < t; i++) cout << ns[i] << '\n';
    cout.flush();

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

    for (int tc = 0; tc < t; tc++) {
        int n = ns[tc];
        int expectedK = kmax[tc];

        long long k_ll = readLLFromCin("k");
        if (k_ll < 1 || k_ll > n / 2) finish(_wa, "k out of allowed range");
        if ((int)k_ll != expectedK) finish(_wa, "k is not the maximum guaranteed value");
        int k = (int)k_ll;

        unordered_map<uint64_t, int> known;
        known.reserve((size_t)min<long long>(hard_cap, (long long)n * 2 + 16));

        while (true) {
            string cmd;
            if (!(cin >> cmd)) finish(_pe, "unexpected EOF while reading command");

            if (cmd == "?") {
                long long u_ll = readLLFromCin("u");
                long long v_ll = readLLFromCin("v");
                if (u_ll < 1 || u_ll > n || v_ll < 1 || v_ll > n) finish(_wa, "query vertex out of range");
                if (u_ll == v_ll) finish(_wa, "query with identical vertices");
                int u = (int)u_ll, v = (int)v_ll;

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

                uint64_t key = packPair(u, v);
                auto it = known.find(key);
                int ans = 0; 
                if (it == known.end()) known.emplace(key, ans);
                else ans = it->second;

                cout << ans << '\n';
                cout.flush();
            } else if (cmd == "!") {
                vector<int> out;
                out.reserve(2 * k);
                for (int i = 0; i < 2 * k; i++) {
                    long long x_ll = readLLFromCin("answer vertex");
                    if (x_ll < 1 || x_ll > n) finish(_wa, "answer vertex out of range");
                    out.push_back((int)x_ll);
                }

                vector<int> seen(n + 1, 0);
                for (int x : out) {
                    if (seen[x]) finish(_wa, "duplicate vertex in answer");
                    seen[x] = 1;
                }
                for (int i = 0; i < 2 * k; i += 2) {
                    if (out[i] == out[i + 1]) finish(_wa, "pair contains identical vertices");
                }

                if (k == 1) {
                    break; 
                }

                int common = -1;
                for (int i = 0; i < 2 * k; i += 2) {
                    int u = out[i], v = out[i + 1];
                    uint64_t key = packPair(u, v);
                    auto it = known.find(key);
                    if (it == known.end()) finish(_wa, "answer uses unqueried pair (not forced in adaptive setting)");
                    int val = it->second;
                    if (common == -1) common = val;
                    else if (common != val) finish(_wa, "answer pairs are not all friends or all non-friends");
                }

                break;
            } else {
                finish(_pe, "unknown command token");
            }
        }
    }

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


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

static long long parseSeedArg(int argc, char** argv) {
    if (argc <= 1) return 1;
    const char* s = argv[1];
    bool neg = false;
    if (*s == '-') {
        neg = true;
        ++s;
    }
    long long x = 0;
    while (*s) {
        if (*s >= '0' && *s <= '9') x = x * 10 + (*s - '0');
        ++s;
    }
    return neg ? -x : x;
}

static int clampN(int n, int maxn) {
    n = max(2, n);
    n = min(maxn, n);
    return n;
}

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

    string mode = opt<string>("mode", "non");
    int maxn = opt<int>("maxn", 100000);
    int nOverride = opt<int>("n", -1);
    long long saltOverride = opt<long long>("salt", LLONG_MIN);

    long long seedArg = parseSeedArg(argc, argv);

    int n = 0;
    if (nOverride != -1) {
        n = clampN(nOverride, maxn);
    } else if (seedArg == 1) {
        n = 2; 
    } else if (seedArg == 2) {
        n = 5; 
    } else if (seedArg == 3) {
        n = maxn; 
    } else {
        int roll = rnd.next(1, 100);
        if (roll <= 70) {
            n = maxn - rnd.next(0, min(10, maxn - 2));
        } else if (roll <= 90) {
            int lo = max(2, maxn - 5000);
            n = rnd.next(lo, maxn);
        } else {
            n = rnd.next(2, maxn);
        }
        n = clampN(n, maxn);

        
        if (n >= 10 && rnd.next(1, 100) <= 65) n = max(2, n - (n % 2)); 
        if (n >= 11 && rnd.next(1, 100) <= 35) n = max(3, n - ((n % 2) == 0)); 
        n = clampN(n, maxn);
    }

    cout << 1 << "\n";

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

    if (mode == "non") {
        
        long long salt;
        if (saltOverride != LLONG_MIN) {
            salt = saltOverride;
        } else if (seedArg == 1) {
            salt = 0;
        } else if (seedArg == 2) {
            salt = 1;
        } else if (seedArg == 3) {
            salt = 9223372036854775783LL;
        } else {
            long long hi = rnd.next(0LL, (1LL << 30) - 1);
            long long lo = rnd.next(0LL, (1LL << 32) - 1);
            salt = (hi << 32) ^ lo;
            salt ^= (seedArg << 1);
            if (salt == LLONG_MIN) salt = 0;
        }

        cout << n << "\n" << salt << "\n";
        return 0;
    }

    quitf(_fail, "Unknown --mode: %s (expected non or adp)", mode.c_str());
    return 0;
}