Problem: cf1973_d
Difficulty: hard
Categories: greedy, math
Time limit: 3000 ms, memory limit: 256 MB

This is an interactive problem.

Fox gave Cat two positive integers $n$ and $k$. She has a hidden array $a_1, \ldots , a_n$ of length $n$, such that $1 \leq a_i \leq n$ for every $i$. Now they are going to play the following game:

For any two integers $l, r$ such that $1 \leq l \leq r \leq n$, define $f(l, r) = (r - l + 1) \cdot \max\limits_{x=l}^r a_x$. In other words, $f(l, r)$ is equal to the maximum of the subarray $a_l, \ldots, a_r$ multiplied by its size.

Cat can ask Fox at most $2 n$ questions about the array. He will tell her two integers $l$ and $x$ ($1 \leq l \leq n, 1 \leq x \leq 10^9$), and she will tell him one integer $p$ as the answer — the smallest positive integer $r$ such that $f(l, r) = x$, or $n+1$ if no such $r$ exists.

Now, Cat needs to find the largest value $m$ such that there exists a sequence $c_1, \ldots, c_{k-1}$ such that $1 \leq c_1 < \ldots < c_{k-1} < n$ and $f(1, c_1) = f(c_1 + 1, c_2) = \ldots = f(c_{k-1}+1, n) = m$. If no such $m$ exists, he should indicate this and take $-1$ as the answer. Note that for $k = 1$, $m$ is always equal to $f(1, n)$.

In other words, the goal is to find the largest $m$ such that you can split the array into exactly $k$ subarrays ($k$ is the constant given to you in the beginning of the interaction) so that all the subarrays have the product of their length and their maximum equal to $m$, or determine that no such $m$ exists. Every element should belong in exactly one of the subarrays.

Cat doesn't know what he should do, so he asked you to play the game for him.

Interaction

Each test contains multiple test cases. The first line contains a single integer $t$ ($1 \leq t \leq 10^3$) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two positive integers $n$ and $k$ ($1 \leq k \leq n \leq 10^4$) — the length of the hidden array and the number of subarrays in the desired split.

Now you are allowed to make queries in the following way — print one line of the form "$\mathtt{?} \ l \ x$" (it must hold that $1 \leq l \leq n$, $1 \leq x \leq 10^9$) and you will receive the smallest integer $r$ such that $l \leq r \leq n$ and $f(l, r) = x$, or $n + 1$ if no such $r$ exists.

If you want to print the answer, output "$\mathtt{!} \ m$" and you will recieve $1$ if your answer is correct and $-1$ otherwise. In the first case, the interaction continues with the next test case. Note that printing the answer doesn't count towards the number of queries made. Please note that you don't receive the values for the next test case immediately, you will first have to read whether your answer to the last test case was correct.

If you receive the integer $-1$ at any moment, it means your program has made an invalid query, exceeded the query limit, or gave an incorrect answer. Your program must terminate immediately to receive a Wrong Answer verdict. Otherwise, you can get an arbitrary verdict because your solution will continue to read from a closed stream.

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

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

It is guaranteed that the total sum of $n$ over the test cases won't exceed $10^4$.

Example

Input

```
3
1 1

1
2 2

1

3

1
6 3

7

2

3

6

1
```

Output

```
! 1

? 1 1

? 2 1

! -1

? 1 9

? 1 6

? 3 6

? 4 6

! 6
```

Note

The hidden arrays in the three testcases are $[1]$, $[1, 2]$ and $[1, 3, 6, 1, 2, 1]$. In the second testcase, no split satisfies the constraints, so the answer is $-1$.

The answer for the first query of the third testcase is $7$ since no valid $r$ exists. For the second query of the third testcase, since $2 \cdot \max(1, 3) = 6$, we will get $2$ as the answer, since $r = 1$ doesn't satisfy the constraint.

The sample interaction guessed all three answers ($1, -1$ and $6$) correctly, so it received $1$ after each answer.

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());
}

struct CaseData {
    int n = 0, k = 0;
    vector<int> a;                 
    vector<int> lg;                
    vector<vector<int>> st;        
    long long answer = -1;

    void buildSparse() {
        lg.assign(n + 1, 0);
        for (int i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;
        int K = lg[n];
        st.assign(K + 1, vector<int>(n + 1, 0));
        for (int i = 1; i <= n; i++) st[0][i] = a[i];
        for (int j = 1; j <= K; j++) {
            int len = 1 << j;
            int half = len >> 1;
            for (int i = 1; i + len - 1 <= n; i++) {
                st[j][i] = max(st[j - 1][i], st[j - 1][i + half]);
            }
        }
    }

    int rangeMax(int l, int r) const {
        int len = r - l + 1;
        int j = lg[len];
        return max(st[j][l], st[j][r - (1 << j) + 1]);
    }

    long long f(int l, int r) const {
        long long mx = rangeMax(l, r);
        long long len = r - l + 1;
        return len * mx;
    }

    int findRForX(int l, long long x) const {
        if (l < 1 || l > n) return n + 1;
        if (x < 1) return n + 1;
        if (f(l, n) < x) return n + 1;
        int lo = l, hi = n, ans = n + 1;
        while (lo <= hi) {
            int mid = (lo + hi) >> 1;
            long long val = f(l, mid);
            if (val >= x) {
                ans = mid;
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
        }
        if (ans == n + 1) return n + 1;
        return (f(l, ans) == x) ? ans : (n + 1);
    }

    bool feasibleByScan(long long m) const {
        int pos = 1;
        for (int seg = 1; seg <= k; seg++) {
            int remainingElems = n - pos + 1;
            int remainingSegs = k - seg + 1;
            if (remainingElems < remainingSegs) return false;

            int curMax = 0;
            bool found = false;
            for (int r = pos; r <= n; r++) {
                curMax = max(curMax, a[r]);
                long long val = 1LL * (r - pos + 1) * curMax;
                if (val == m) {
                    pos = r + 1;
                    found = true;
                    break;
                }
                if (val > m) return false;
            }
            if (!found) return false;
        }
        return pos == n + 1;
    }

    long long computeAnswer() const {
        if (k == 1) return 1LL * n * (*max_element(a.begin() + 1, a.end()));

        vector<int> prefMax(n + 1, 0);
        for (int i = 1; i <= n; i++) prefMax[i] = max(prefMax[i - 1], a[i]);

        int maxFirstEnd = n - (k - 1);
        for (int r = maxFirstEnd; r >= 1; r--) {
            long long m = 1LL * r * prefMax[r];
            if (feasibleByScan(m)) return m;
        }
        return -1;
    }
};

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

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

    vector<CaseData> cases;
    cases.reserve(t);

    long long totalBudget = 0;
    for (int tc = 0; tc < t; tc++) {
        CaseData cs;
        cs.n = inf.readInt(1, 10000, "n");
        cs.k = inf.readInt(1, cs.n, "k");
        cs.a.assign(cs.n + 1, 0);
        for (int i = 1; i <= cs.n; i++) {
            cs.a[i] = inf.readInt(1, cs.n, "a[i]");
        }
        cs.buildSparse();
        cs.answer = cs.computeAnswer();
        cases.push_back(std::move(cs));
        totalBudget += 2LL * cases.back().n;
    }

    query_limit = totalBudget;
    log_metrics(); 

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

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

    for (int tc = 0; tc < t; tc++) {
        const CaseData& cs = cases[tc];

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

        while (true) {
            string cmd;
            if (!(cin >> cmd)) {
                finish(_wa, "Unexpected EOF from contestant");
            }

            if (cmd == "?") {
                long long l, x;
                if (!(cin >> l >> x)) {
                    cout << -1 << "\n";
                    cout.flush();
                    finish(_pe, "Malformed query");
                }
                if (l < 1 || l > cs.n || x < 1 || x > 1000000000LL) {
                    cout << -1 << "\n";
                    cout.flush();
                    finish(_wa, "Invalid query parameters");
                }

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

                int r = cs.findRForX((int)l, x);
                cout << r << "\n";
                cout.flush();
            } else if (cmd == "!") {
                long long m;
                if (!(cin >> m)) {
                    cout << -1 << "\n";
                    cout.flush();
                    finish(_pe, "Malformed answer");
                }

                if (m == cs.answer) {
                    cout << 1 << "\n";
                    cout.flush();
                    break;
                } else {
                    cout << -1 << "\n";
                    cout.flush();
                    finish(_wa, "Wrong answer");
                }
            } else {
                cout << -1 << "\n";
                cout.flush();
                finish(_pe, "Unknown command token");
            }
        }
    }

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


Adaptive interactor (C++):

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

static vector<int> buildHardArray(long long seedVal, int n) {
    vector<int> a(n + 1, 1);

    if (seedVal == 1) {
        a.assign(2, 1);
        return a;
    }
    if (seedVal == 2) {
        a.assign(3, 1);
        a[1] = 1;
        a[2] = 2;
        return a;
    }
    if (seedVal == 3) {
        a.assign(7, 1);
        a[1] = 1;
        a[2] = 3;
        a[3] = 6;
        a[4] = 1;
        a[5] = 2;
        a[6] = 1;
        return a;
    }

    int type = rnd.next(1, 4);

    if (type == 1) {
        for (int i = 1; i <= n; i++) a[i] = i;
        return a;
    }

    if (type == 2) {
        int b = rnd.next(10, 200);
        int cur = rnd.next(1, min(n, 5));
        for (int i = 1; i <= n; i++) {
            if (i % b == 1 && i > 1) {
                int drop = rnd.next(0, max(0, b / 3));
                cur = max(1, cur - drop);
            }
            cur = min(n, cur + rnd.next(0, 2));
            a[i] = cur;
        }
        a[n] = n;
        int tailStart = max(1, n - 700);
        for (int i = tailStart; i <= n; i++) {
            a[i] = max(a[i], min(n, i - tailStart + 1));
        }
        for (int i = 1; i <= n; i++) a[i] = min(n, max(1, a[i]));
        a[n] = n;
        return a;
    }

    if (type == 3) {
        int period = rnd.next(15, 60);
        int spikeVal = rnd.next(1, max(2, n / period));
        for (int i = 1; i <= n; i++) {
            if (i % period == 0) {
                spikeVal = min(n, spikeVal + rnd.next(1, 5));
                a[i] = spikeVal;
            } else {
                int within = i % period;
                a[i] = min(n, within + rnd.next(0, 2));
            }
        }
        for (int i = 2; i <= n; i++) a[i] = max(a[i], a[i - 1]);
        a[n] = n;
        return a;
    }

    for (int i = 1; i <= n; i++) {
        int val = i;
        if (rnd.next(0, 9) == 0) val = max(1, i - rnd.next(1, min(200, i)));
        int rem = n - i;
        if (rem > 0 && rnd.next(0, 19) == 0) val = min(n, i + rnd.next(1, min(200, rem)));
        a[i] = min(n, max(1, val));
    }
    int pref = 0;
    for (int i = 1; i <= n; i++) {
        pref = max(pref, a[i]);
        if (i % 3 == 0 && pref < min(n, i)) {
            a[i] = max(a[i], min(n, i));
            pref = max(pref, a[i]);
        }
    }
    for (int i = 1; i <= n; i++) a[i] = min(n, max(1, a[i]));
    a[n] = n;
    return a;
}

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

    string mode = opt<string>("mode", "non");
    int nOpt = opt<int>("n", 10000);
    int kOpt = opt<int>("k", -1);

    long long seedVal = 1;
    if (argc >= 2) seedVal = atoll(argv[1]);

    int n, k;
    vector<int> a;

    if (seedVal == 1) {
        n = 1;
        k = 1;
        a = buildHardArray(seedVal, n);
    } else if (seedVal == 2) {
        n = 2;
        k = 2;
        a = buildHardArray(seedVal, n);
    } else if (seedVal == 3) {
        n = 6;
        k = 3;
        a = buildHardArray(seedVal, n);
    } else {
        n = nOpt;
        if (n < 1) n = 1;
        if (n > 10000) n = 10000;

        if (kOpt != -1) {
            k = kOpt;
        } else {
            int base = rnd.next(2, 8);
            k = max(1, n / base);
            k = min(k, n);
            int left = -min(50, k - 1);
            int right = min(50, n - k);
            int wiggle = rnd.next(left, right);
            k += wiggle;
            if (k < 1) k = 1;
            if (k > n) k = n;
        }

        a = buildHardArray(seedVal, n);
    }

    cout << 1 << "\n";
    if (mode == "non") {
        cout << n << " " << k << "\n";
        for (int i = 1; i <= n; i++) {
            if (i > 1) cout << " ";
            cout << a[i];
        }
        cout << "\n";
        return 0;
    }

    if (mode == "adp") {
        cout << n << " " << k << "\n";

        int deltaGlobal = 0;
        if (seedVal > 3) deltaGlobal = rnd.next(0, 30);

        for (int i = 1; i <= n; i++) {
            int delta = deltaGlobal;
            if (seedVal > 3) {
                if (i % 97 == 0 || i % 101 == 0) {
                    delta = max(delta, n);
                } else if (i % 7 == 0) {
                    delta = max(delta, 5);
                } else {
                    delta = max(delta, rnd.next(0, deltaGlobal));
                }
            }

            long long loLL = (long long)a[i] - (long long)delta;
            long long hiLL = (long long)a[i] + (long long)delta;
            int lo = (int)max(1LL, loLL);
            int hi = (int)min((long long)n, hiLL);
            if (lo > hi) swap(lo, hi);
            cout << lo << " " << hi << "\n";
        }
        return 0;
    }

    quitf(_fail, "Unknown mode: %s", mode.c_str());
    return 0;
}