Problem: cf2049_e
Difficulty: hard
Categories: search
Time limit: 2000 ms, memory limit: 256 MB

You, a wizard whose creation was destroyed by a dragon, are determined to hunt it down with a magical AOE tracker. But it seems to be toyed with...

This is an interactive problem.

There is a hidden binary array $a$ of length $n$ ($\mathbf{n}$ is a power of 2) and a hidden integer $k\ (2 \le k \le n - 1)$. The array $a$ contains exactly one 1 (and all other elements are 0). For two integers $l$ and $r$ ($1 \le l \le r \le n$), define the range sum $s(l, r) = a_l + a_{l+1} + \cdots + a_r$.

You have a magical device that takes ranges and returns range sums, but it returns the opposite result when the range has length at least $k$. Formally, in one query, you can give it a pair of integers $[l, r]$ where $1 \le l \le r \le n$, and it will return either $0$ or $1$ according to the following rules:

* If $r - l + 1 < k$, it will return $s(l, r)$.
* If $r - l + 1 \ge k$, it will return $1 - s(l, r)$.

Find $k$ using at most $33$ queries.

The device is not adaptive. It means that the hidden $a$ and $k$ are fixed before the interaction and will not 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 500$). The description of the test cases follows.

The first line of each test case contains one positive integer $n$ ($4 \le n \le 2^{30}$) — the length of the hidden array. It is guaranteed that $\mathbf{n}$ is a power of 2; that is, $n = 2^m$ for some non-negative integer $m$.

You can make queries in the following way — print one line of the form "$\mathtt{?}\,l\,r$" where $1 \le l \le r \le n$. After that, read a single integer: $0$ or $1$, as described in the statement.

If you want to print the answer $k$, output "$\mathtt{!}\,k$". Then, the interaction continues with the next test case.

Printing the answer does not count towards the number of queries made.

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 receive 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
8

0

0

1

0

4

1

0
```

Output

```
? 3 5

? 1 8

? 4 8

? 3 8

! 6

? 3 3

? 3 4

! 2
```

Note

In the first test case, $k = 6$ and the 1 in the hidden array is at index 6, so $a = [0, 0, 0, 0, 0, 1, 0, 0]$.

* For the query 3 5, since $5-3+1 = 3 < k$, the device answers correctly. Since 6 is not contained in the range $[3, 5]$, the device answers $0$.
* For the query 1 8, since $8 - 1 + 1 = 8 \ge k$, the device answers $0$ incorrectly.
* For the query 4 8, since $8 - 4 + 1 = 5 < k$, the device answers $1$ correctly.
* For the query 3 8, since $8 - 3 + 1 = 6 \ge k$, the device answers $0$ incorrectly.

The example solution then outputs $6$ as the answer, which is correct.

In the second test case, $k = 2$ and the 1 in the hidden array is at index 3, so $a = [0, 0, 1, 0]$.

Note that the example solution may not have enough information to determine $k$ above; this is only an example.

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 = 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& s) {
    return (cin >> s) ? true : false;
}

static bool parseLongLongStrict(const string& s, long long& out) {
    if (s.empty()) return false;
    size_t i = 0;
    bool neg = false;
    if (s[i] == '+' || s[i] == '-') {
        neg = (s[i] == '-');
        i++;
    }
    if (i >= s.size()) return false;
    long long val = 0;
    for (; i < s.size(); i++) {
        char c = s[i];
        if (c < '0' || c > '9') return false;
        int d = c - '0';
        if (!neg) {
            if (val > (LLONG_MAX - d) / 10) return false;
            val = val * 10 + d;
        } else {
            if (val < (LLONG_MIN + d) / 10) return false;
            val = val * 10 - d;
        }
    }
    out = val;
    return true;
}

static bool isPowerOfTwo(long long x) {
    return x >= 1 && (x & (x - 1)) == 0;
}

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

    int t = inf.readInt();
    if (t < 1 || t > 500) finish(_pe, "Invalid t in hidden input");

    vector<long long> n(t), k(t), pos(t);
    for (int i = 0; i < t; i++) {
        n[i] = inf.readLong();
        k[i] = inf.readLong();
        pos[i] = inf.readLong();

        if (n[i] < 4LL || n[i] > (1LL << 30) || !isPowerOfTwo(n[i])) finish(_pe, "Invalid n in hidden input");
        if (k[i] < 2LL || k[i] > n[i] - 1) finish(_pe, "Invalid k in hidden input");
        if (pos[i] < 1LL || pos[i] > n[i]) finish(_pe, "Invalid pos in hidden input");
    }

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

    log_metrics(); 

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

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

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

            if (cmd == "?") {
                string sl, sr;
                if (!readToken(sl) || !readToken(sr)) finish(_pe, "Incomplete query");

                long long l, r;
                if (!parseLongLongStrict(sl, l) || !parseLongLongStrict(sr, r)) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Non-integer query bounds");
                }

                if (!(1LL <= l && l <= r && r <= n[tc])) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Query out of bounds");
                }

                queries++;
                if (queries > hard_cap) {
                    cout << -1 << '\n';
                    cout.flush();
                    finish(_pe, "Hard cap exceeded");
                }

                long long len = r - l + 1;
                int sum = (l <= pos[tc] && pos[tc] <= r) ? 1 : 0;
                int ans = (len < k[tc]) ? sum : (1 - sum);

                cout << ans << '\n';
                cout.flush();
            } else if (cmd == "!") {
                string sk;
                if (!readToken(sk)) finish(_pe, "Incomplete answer");
                long long guess;
                if (!parseLongLongStrict(sk, guess)) finish(_pe, "Non-integer answer");

                if (guess != k[tc]) finish(_wa, "Wrong k");
                break;
            } else {
                finish(_pe, "Unknown command");
            }
        }
    }

    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";
        tout.flush();
    } catch (...) {
        
    }
}

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

static uint64_t fnv1a64(const string& s) {
    uint64_t h = 1469598103934665603ULL;
    for (unsigned char c : s) {
        h ^= (uint64_t)c;
        h *= 1099511628211ULL;
    }
    return h;
}

static uint64_t splitmix64(uint64_t x) {
    x += 0x9E3779B97F4A7C15ULL;
    x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ULL;
    x = (x ^ (x >> 27)) * 0x94D049BB133111EBULL;
    return x ^ (x >> 31);
}

static bool parseLL(const string& s, long long& out) {
    if (s.empty()) return false;
    int i = 0;
    bool neg = false;
    if (s[0] == '-') {
        neg = true;
        i = 1;
        if ((int)s.size() == 1) 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 (!neg) {
            if (val > (LLONG_MAX - d) / 10) return false;
            val = val * 10 + d;
        } else {
            if (val < (LLONG_MIN + d) / 10) return false;
            val = val * 10 - d;
        }
    }
    out = val;
    return true;
}

static bool isPowerOfTwo(long long x) {
    return x >= 1 && (x & (x - 1)) == 0;
}

struct Interval {
    long long l, r;
};

static long long measureIntervals(const vector<Interval>& v) {
    long long sum = 0;
    for (const auto& it : v) {
        if (it.l <= it.r) sum += (it.r - it.l + 1);
    }
    return sum;
}

static vector<Interval> intersectWith(const vector<Interval>& v, long long l, long long r) {
    vector<Interval> res;
    if (l > r) return res;
    for (const auto& it : v) {
        long long nl = max(it.l, l);
        long long nr = min(it.r, r);
        if (nl <= nr) res.push_back({nl, nr});
    }
    return res;
}

static vector<Interval> subtractRange(const vector<Interval>& v, long long l, long long r) {
    vector<Interval> res;
    if (l > r) return v;
    for (const auto& it : v) {
        if (it.r < l || it.l > r) {
            res.push_back(it);
            continue;
        }
        if (it.l < l) res.push_back({it.l, l - 1});
        if (it.r > r) res.push_back({r + 1, it.r});
    }
    return res;
}

struct Cell {
    long long kl, kr;           
    vector<Interval> pos;       
};

static bool samePos(const vector<Interval>& a, const vector<Interval>& b) {
    if (a.size() != b.size()) return false;
    for (size_t i = 0; i < a.size(); i++) {
        if (a[i].l != b[i].l || a[i].r != b[i].r) return false;
    }
    return true;
}

static void mergeCells(vector<Cell>& cells) {
    if (cells.empty()) return;
    sort(cells.begin(), cells.end(), [](const Cell& x, const Cell& y) {
        if (x.kl != y.kl) return x.kl < y.kl;
        return x.kr < y.kr;
    });
    vector<Cell> merged;
    merged.reserve(cells.size());
    for (auto& c : cells) {
        if (c.kl > c.kr) continue;
        if (c.pos.empty()) continue;
        if (merged.empty()) {
            merged.push_back(std::move(c));
            continue;
        }
        Cell& back = merged.back();
        if (back.kr + 1 == c.kl && samePos(back.pos, c.pos)) {
            back.kr = c.kr;
        } else {
            merged.push_back(std::move(c));
        }
    }
    cells.swap(merged);
}

static vector<Cell> applyAnswer(const vector<Cell>& cells, long long l, long long r, long long L, int ans) {
    vector<Cell> out;
    out.reserve(cells.size() * 2);

    for (const auto& cell : cells) {
        
        long long aL = cell.kl;
        long long aR = min(cell.kr, L);
        if (aL <= aR) {
            int kLeq = 1;
            int posIn = ans ^ kLeq;
            vector<Interval> np = cell.pos;
            if (posIn) np = intersectWith(np, l, r);
            else np = subtractRange(np, l, r);
            if (!np.empty()) out.push_back({aL, aR, std::move(np)});
        }
        
        long long bL = max(cell.kl, L + 1);
        long long bR = cell.kr;
        if (bL <= bR) {
            int kLeq = 0;
            int posIn = ans ^ kLeq;
            vector<Interval> np = cell.pos;
            if (posIn) np = intersectWith(np, l, r);
            else np = subtractRange(np, l, r);
            if (!np.empty()) out.push_back({bL, bR, std::move(np)});
        }
    }

    mergeCells(out);
    return out;
}

static long long measureK(const vector<Cell>& cells) {
    long long sum = 0;
    for (const auto& c : cells) {
        if (c.kl <= c.kr) sum += (c.kr - c.kl + 1);
    }
    return sum;
}

static __int128 measurePairs(const vector<Cell>& cells) {
    __int128 sum = 0;
    for (const auto& c : cells) {
        if (c.kl > c.kr) continue;
        long long klen = c.kr - c.kl + 1;
        long long p = measureIntervals(c.pos);
        sum += (__int128)klen * (__int128)p;
    }
    return sum;
}

static bool kFeasibleAndAllSame(const vector<Cell>& cells, long long kGuess, bool& guessFeasible) {
    guessFeasible = false;
    bool allSame = true;
    bool any = false;
    for (const auto& c : cells) {
        if (c.kl > c.kr) continue;
        if (c.pos.empty()) continue;
        any = true;
        if (c.kl <= kGuess && kGuess <= c.kr) guessFeasible = true;
        if (!(c.kl == c.kr && c.kl == kGuess)) allSame = false;
    }
    if (!any) {
        
        finish(_pe, "internal: empty feasible set");
    }
    return allSame;
}

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

    int t = 0;
    try {
        t = inf.readInt();
    } catch (...) {
        finish(_pe, "failed to read t from inf");
    }
    if (t < 1 || t > 500) finish(_pe, "t out of bounds");

    vector<string> toks;
    while (!inf.seekEof()) toks.push_back(inf.readToken());

    vector<long long> ns(t, -1), ks(t, -1), ps(t, -1);
    bool nonAdaptive = false;

    if (toks.size() == (size_t)t) {
        for (int i = 0; i < t; i++) {
            long long x;
            if (!parseLL(toks[i], x)) finish(_pe, "bad n token");
            ns[i] = x;
        }
    } else if (toks.size() == (size_t)3 * t) {
        nonAdaptive = true;
        for (int i = 0; i < t; i++) {
            long long n, k, p;
            if (!parseLL(toks[3 * i + 0], n)) finish(_pe, "bad n token");
            if (!parseLL(toks[3 * i + 1], k)) finish(_pe, "bad k token");
            if (!parseLL(toks[3 * i + 2], p)) finish(_pe, "bad pos token");
            ns[i] = n;
            ks[i] = k;
            ps[i] = p;
        }
    } else {
        finish(_pe, "inf format unsupported (expected t*n or t*(n,k,pos))");
    }

    
    
    
    if (!nonAdaptive) {
        uint64_t base = fnv1a64(inf.name);
        for (int i = 0; i < t; i++) {
            long long n = ns[i];
            if (n < 4) finish(_pe, "n invalid while synthesizing k/pos");
            uint64_t seed = base;
            seed ^= (uint64_t)n * 0x9E3779B97F4A7C15ULL;
            seed ^= (uint64_t)(i + 1) * 0xBF58476D1CE4E5B9ULL;
            uint64_t z = splitmix64(seed);
            long long k = 2 + (long long)(z % (uint64_t)(n - 2)); 
            long long p = 1 + (long long)(((z >> 32) ^ z) % (uint64_t)n); 
            ks[i] = k;
            ps[i] = p;
        }
        nonAdaptive = true;
    }

    for (int i = 0; i < t; i++) {
        long long n = ns[i];
        if (n < 4 || n > (1LL << 30) || !isPowerOfTwo(n)) finish(_pe, "n invalid in inf");
        if (nonAdaptive) {
            long long k = ks[i], p = ps[i];
            if (k < 2 || k > n - 1) finish(_pe, "k invalid in inf");
            if (p < 1 || p > n) finish(_pe, "pos invalid in inf");
        }
    }

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

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

    log_metrics(); 

    for (int tc = 0; tc < t; tc++) {
        long long n = ns[tc];
        cout << n << "\n";
        cout.flush();

        bool fixed = nonAdaptive;
        long long fixedK = fixed ? ks[tc] : -1;
        long long fixedPos = fixed ? ps[tc] : -1;

        vector<Cell> cells;
        if (!fixed) {
            cells.push_back({2, n - 1, vector<Interval>{{1, n}}});
        }

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

            if (cmd == "?") {
                string sl, sr;
                if (!(cin >> sl >> sr)) finish(_pe, "bad query format");
                long long l, r;
                if (!parseLL(sl, l) || !parseLL(sr, r)) finish(_pe, "non-integer in query");
                if (!(1 <= l && l <= r && r <= n)) finish(_pe, "query range out of bounds");

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

                long long L = r - l + 1;
                int reply = 0;

                if (fixed) {
                    int posIn = (l <= fixedPos && fixedPos <= r) ? 1 : 0;
                    int lenGeK = (L >= fixedK) ? 1 : 0;
                    reply = posIn ^ lenGeK;
                } else {
                    vector<Cell> c0 = applyAnswer(cells, l, r, L, 0);
                    vector<Cell> c1 = applyAnswer(cells, l, r, L, 1);

                    long long m0 = measureK(c0);
                    long long m1 = measureK(c1);

                    if (m0 == 0 && m1 == 0) finish(_pe, "internal: no feasible answer");

                    if (m1 > m0) {
                        reply = 1;
                        cells.swap(c1);
                    } else if (m0 > m1) {
                        reply = 0;
                        cells.swap(c0);
                    } else {
                        __int128 p0 = measurePairs(c0);
                        __int128 p1 = measurePairs(c1);
                        if (p1 > p0) {
                            reply = 1;
                            cells.swap(c1);
                        } else {
                            reply = 0;
                            cells.swap(c0);
                        }
                    }
                }

                cout << reply << "\n";
                cout.flush();
                continue;
            }

            if (cmd == "!") {
                string sk;
                if (!(cin >> sk)) finish(_pe, "bad answer format");
                long long kGuess;
                if (!parseLL(sk, kGuess)) finish(_pe, "non-integer k");
                if (!(2 <= kGuess && kGuess <= n - 1)) finish(_pe, "k out of bounds");

                if (fixed) {
                    if (kGuess != fixedK) finish(_wa, "wrong k");
                } else {
                    bool guessFeasible = false;
                    bool allSame = kFeasibleAndAllSame(cells, kGuess, guessFeasible);
                    if (!guessFeasible) finish(_wa, "k not feasible");
                    if (!allSame) finish(_wa, "k not uniquely determined");
                }
                break; 
            }

            finish(_pe, "unknown command");
        }
    }

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


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

static long long clampll(long long x, long long lo, long long hi) {
    if (x < lo) return lo;
    if (x > hi) return hi;
    return x;
}

static bool isPowerOfTwo(long long x) {
    return x >= 1 && (x & (x - 1)) == 0;
}

static long long pickN(long long seed) {
    if (seed == 1 || seed == 2) return 4;
    if (seed == 3) return (1LL << 30);

    int coin = rnd.next(0, 99);
    int m;
    if (coin < 70) m = rnd.next(25, 30);
    else if (coin < 90) m = rnd.next(16, 30);
    else m = rnd.next(2, 30);
    return 1LL << m;
}

static long long pickK(long long n, long long seed) {
    if (seed == 1) return 2;
    if (seed == 2) return 3;
    if (seed == 3) return n - 1;

    int pat = rnd.next(0, 99);
    long long k = 2;

    if (pat < 22) {
        long long hi = min(n - 1, 20LL);
        k = rnd.next(2LL, hi);
    } else if (pat < 44) {
        long long lo = max(2LL, (n - 1) - 19LL);
        k = rnd.next(lo, n - 1);
    } else if (pat < 70) {
        long long base = n / 2;
        long long lim = max(1LL, n / 16);
        long long delta = rnd.next(-lim, lim);
        k = base + delta;
    } else if (pat < 88) {
        int m = 0;
        while ((1LL << (m + 1)) <= n) m++;
        int x = rnd.next(1, max(1, m - 1));
        long long p2 = 1LL << x;
        int var = rnd.next(0, 2);
        if (var == 0) k = p2;
        else if (var == 1) k = p2 + 1;
        else k = p2 - 1;
    } else {
        k = rnd.next(2LL, n - 1);
    }

    return clampll(k, 2LL, n - 1);
}

static long long pickPos(long long n, long long k, long long seed) {
    if (seed == 1) return n;
    if (seed == 2) return 2;
    if (seed == 3) return n / 2;

    int pat = rnd.next(0, 99);
    long long pos;

    if (pat < 25) {
        pos = (rnd.next(0, 1) ? 1LL : n);
    } else if (pat < 55) {
        vector<long long> cand;
        cand.push_back(n / 2);
        cand.push_back(min(n, n / 2 + 1));
        cand.push_back(max(1LL, n / 4));
        cand.push_back(min(n, (3LL * n) / 4));
        cand.push_back(clampll(k, 1LL, n));
        cand.push_back(clampll(n - k + 1, 1LL, n));
        pos = cand[rnd.next(0, (int)cand.size() - 1)];
    } else {
        pos = rnd.next(1LL, n);
    }

    return clampll(pos, 1LL, n);
}

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

    string mode = opt<string>("mode", "non");
    long long seed = 1;
    if (argc >= 2) seed = atoll(argv[1]);

    long long nOpt = opt<long long>("n", -1LL);
    long long kOpt = opt<long long>("k", -1LL);
    long long posOpt = opt<long long>("pos", -1LL);

    long long n = (nOpt > 0 ? nOpt : pickN(seed));
    ensuref(4LL <= n && n <= (1LL << 30), "n out of bounds");
    ensuref(isPowerOfTwo(n), "n must be a power of two");

    if (mode == "non") {
        long long k = (kOpt != -1 ? kOpt : pickK(n, seed));
        ensuref(2LL <= k && k <= n - 1, "k out of bounds");

        long long pos = (posOpt != -1 ? posOpt : pickPos(n, k, seed));
        ensuref(1LL <= pos && pos <= n, "pos out of bounds");

        cout << 1 << "\n";
        cout << n << " " << k << " " << pos << "\n";
    } else if (mode == "adp") {
        
        
        
        long long k = (kOpt != -1 ? kOpt : pickK(n, seed));
        ensuref(2LL <= k && k <= n - 1, "k out of bounds");

        long long pos = (posOpt != -1 ? posOpt : pickPos(n, k, seed));
        ensuref(1LL <= pos && pos <= n, "pos out of bounds");

        cout << 1 << "\n";
        cout << n << " " << k << " " << pos << "\n";
    } else {
        ensuref(false, "unknown --mode (use non/adp)");
    }

    return 0;
}