Problem: cf2135_d2
Difficulty: hard
Categories: math
Time limit: 3000 ms, memory limit: 512 MB

This is the hard version of the problem. The difference between the versions is that in this version, the sum of the lengths of the articles over all queries must not exceed $2.5\cdot 10^4$.

This is an interactive problem.

The RiOI Team has recently developed a text editor named RiOI Editor. The editor works with exactly one integer parameter $W$ — the width of each line. It is known that $1 \leq W \leq 10^5$.

As you cannot understand the RiOI Language, from your point of view, words differ from each other only by their length. Hence, an article of length $n$ is defined as a sequence $a$ consisting of $n$ positive integers, where $a_i$ is the length of the $i$-th word in the article. The RiOI Editor displays the article $[a_1, a_2,\ldots, a_n]$ on screen as follows:

* If $\max(a_1, a_2, \ldots, a_n) > W$, the editor is unable to display the article;
* Otherwise, the editor is able to display the article by the following process:
  + Initially, $l = 1$, and $s = 0$. During the whole process, $l$ always denotes the current number of lines in the editor, and $s$ always denotes the sum of lengths of words in the last line;
  + Then, for each $1\le i\le n$:
    - If $s + a_i \leq W$, the word is inserted at the end of the current line. Thus, $l$ remains unchanged, and $s$ gets increased by $a_i$.
    - Otherwise, the word is inserted into a new line. Thus, $l$ becomes $l + 1$, and $s$ becomes $a_i$.
  + The number of lines needed to display the article is the final value of $l$.

You are very interested in the editor, so you decide to find out the value of $W$ by inputting some articles into the editor and observing the number of lines needed to display each article.

Formally, you can query the jury at most $2$ times. In each query, you input an article $[a_1, a_2, \ldots, a_n]$ ($1\leq n \leq 10^5$) to the editor, and the jury will respond to you with:

* The number of lines needed to display the article, if the editor is able to display it;
* $0$, if the editor is unable to display the article.

Additional constraint in this version: the sum of the lengths of the articles (i.e., $n$) over all queries must not exceed $2.5\cdot 10^4$.

Input

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

Interaction

For each test case, you can make up to $2$ queries to find out the value of $W$. It is guaranteed that $1\leq W\leq 10^5$.

To make a query, you should print a new line in the following format:

* $\texttt{? } n\texttt{ }a_1\texttt{ }a_2\texttt{ }\ldots\texttt{ }a_n$ ($1 \leq n, a_i \leq 10^5$) — the article you input to the editor.

The sum of $n$ over all queries must not exceed $2.5\cdot 10^4$.

At the end of each query, the jury will print an integer, as described in the statements.

To report that you have found the value of $W$, print a new line in the following format:

* $\texttt{! } W$ — the parameter of the editor.

Printing the answer does not count as one of the $2$ queries.

After that, proceed to process the next test case or terminate the program if it was the last test case.

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.

The interactor in this problem is adaptive. It means that the value of $W$ may change during the interaction, but it is guaranteed that there is always at least one integer $W$ satisfying all the queries.

Example

Input

```
2

2

1

0
```

Output

```
? 5 1 9 4 6 1

? 2 10 10

! 20
? 1 2

! 1
```

Note

In the first test case:

* For the first query, the total length of the words is $1+9+4+6+1=21$, and the article is displayed in two lines, so $W<21$;
* For the second query, the total length of the words is $10+10=20$, and the article is displayed in one line, so $W\ge 20$.

Thus, we have determined $W = 20$.

In the second test case, the editor cannot display the article in the only query. Thus, $W < 2$, so it can only be $1$.

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

static bool readToken(string& s) {
    return (cin >> s) ? true : false;
}

static bool readLongLong(long long& x) {
    return (cin >> x) ? true : false;
}

static long long linesNeededIfDisplayable(const vector<int>& a, int W) {
    int mx = 0;
    for (int v : a) mx = max(mx, v);
    if (mx > W) return 0;

    long long l = 1;
    long long s = 0;
    for (int v : a) {
        if (s + v <= W) {
            s += v;
        } else {
            l++;
            s = v;
        }
    }
    return l;
}

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

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

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

    vector<int> hiddenW(t);
    for (int i = 0; i < t; i++) {
        int w = 0;
        try {
            w = inf.readInt();
        } catch (...) {
            query_limit = 25000;
            log_metrics();
            finish(_fail, "Failed to read W from inf");
        }
        if (w < 1 || w > 100000) {
            query_limit = 25000;
            log_metrics();
            finish(_fail, "Invalid W in inf");
        }
        hiddenW[i] = w;
    }

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

    
    log_metrics();

    
    cout << t << "\n" << flush;

    for (int tc = 0; tc < t; tc++) {
        int W = hiddenW[tc];

        long long query_count = 0;
        long long sum_n_this_case = 0;

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

            if (cmd == "?") {
                long long nll = 0;
                if (!readLongLong(nll)) {
                    cout << -1 << "\n" << flush;
                    finish(_pe, "Malformed query: missing n");
                }
                if (nll < 1 || nll > 100000) {
                    cout << -1 << "\n" << flush;
                    finish(_wa, "Invalid query: n out of range");
                }
                int n = (int)nll;

                vector<int> a;
                a.reserve(n);
                for (int i = 0; i < n; i++) {
                    long long xll = 0;
                    if (!readLongLong(xll)) {
                        cout << -1 << "\n" << flush;
                        finish(_pe, "Malformed query: not enough a_i");
                    }
                    if (xll < 1 || xll > 100000) {
                        cout << -1 << "\n" << flush;
                        finish(_wa, "Invalid query: a_i out of range");
                    }
                    a.push_back((int)xll);
                }

                query_count++;
                sum_n_this_case += n;
                queries += n;

                if (queries > hard_cap) {
                    cout << -1 << "\n" << flush;
                    finish(_pe, "Hard cap exceeded (possible infinite loop/output spam)");
                }

                long long ans = linesNeededIfDisplayable(a, W);
                cout << ans << "\n" << flush;
            } else if (cmd == "!") {
                long long guess = 0;
                if (!readLongLong(guess)) {
                    cout << -1 << "\n" << flush;
                    finish(_pe, "Malformed answer: missing W");
                }
                if (guess < 1 || guess > 100000) {
                    cout << -1 << "\n" << flush;
                    finish(_wa, "Answer W out of range");
                }
                if ((int)guess != W) {
                    finish(_wa, "Wrong answer");
                }
                break; 
            } else {
                cout << -1 << "\n" << flush;
                finish(_pe, "Unknown command (expected '?' or '!')");
            }
        }

        (void)query_count;
        (void)sum_n_this_case;
    }

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

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

static string trim_copy(string s) {
    size_t i = 0;
    while (i < s.size() && isspace((unsigned char)s[i])) i++;
    size_t j = s.size();
    while (j > i && isspace((unsigned char)s[j - 1])) j--;
    return s.substr(i, j - i);
}

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

static bool read_ll(long long& x) {
    if (!(cin >> x)) return false;
    return true;
}

struct Feasible {
    int L = 1, R = 100000;
};

struct ReplyChoice {
    int reply = 0;
    int newL = 1, newR = 0; 
    int size() const { return (newL <= newR) ? (newR - newL + 1) : 0; }
};

static int compute_lines_greedy(const vector<int>& a, int W) {
    int l = 1;
    int s = 0;
    for (int x : a) {
        if (s + x <= W) {
            s += x;
        } else {
            l++;
            s = x;
        }
    }
    return l;
}

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

    int t = 0;
    try {
        t = inf.readInt(1, 10, "t");
    } catch (...) {
        finish(_pe, "failed to read t from inf");
    }

    query_limit = 2LL * t;
    log_metrics(); 

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

    auto read_nonempty_line_from_inf = [&]() -> string {
        while (true) {
            if (inf.seekEof()) return string();
            string line;
            try {
                line = inf.readLine();
            } catch (...) {
                return string();
            }
            line = trim_copy(line);
            if (!line.empty()) return line;
        }
    };

    long long total_n_over_all_queries = 0;
    const long long sum_n_limit = 25000;
    const long long hard_cap = max(200000LL, 10LL * query_limit);

    for (int tc = 1; tc <= t; tc++) {
        string line = read_nonempty_line_from_inf();
        if (line.empty()) finish(_pe, "unexpected EOF while reading test case parameters");

        vector<long long> vals;
        {
            stringstream ss(line);
            long long x;
            while (ss >> x) vals.push_back(x);
        }
        if (vals.empty()) finish(_pe, "empty parameter line for test case");
        long long a0 = vals[0];
        long long a1 = (vals.size() >= 2 ? vals[1] : vals[0]);

        if (a0 < 1 || a0 > 100000 || a1 < 1 || a1 > 100000) finish(_pe, "inf parameters out of range");
        int L = (int)a0, R = (int)a1;
        if (L > R) swap(L, R);

        Feasible feasible{L, R};
        int queries_in_case = 0;

        while (true) {
            string tok;
            if (!read_token(tok)) finish(_pe, "unexpected EOF from contestant");

            if (tok == "?") {
                long long nll;
                if (!read_ll(nll)) finish(_pe, "missing n after '?'");
                if (nll < 1 || nll > 100000) finish(_pe, "n out of range");
                int n = (int)nll;

                queries++;
                queries_in_case++;
                total_n_over_all_queries += n;
                if (queries > hard_cap) finish(_pe, "too many queries (hard cap exceeded)");
                if (total_n_over_all_queries > sum_n_limit) finish(_pe, "sum of n over all queries exceeded 25000");
                log_metrics(); 

                vector<int> a(n);
                int maxa = 0;
                for (int i = 0; i < n; i++) {
                    long long xll;
                    if (!read_ll(xll)) finish(_pe, "not enough a_i values");
                    if (xll < 1 || xll > 100000) finish(_pe, "a_i out of range");
                    a[i] = (int)xll;
                    maxa = max(maxa, a[i]);
                }

                auto response_at = [&](int W, unordered_map<int,int>& memo) -> int {
                    if (W < maxa) return 0;
                    auto it = memo.find(W);
                    if (it != memo.end()) return it->second;
                    int v = compute_lines_greedy(a, W);
                    memo.emplace(W, v);
                    return v;
                };

                auto first_width_leq_lines = [&](int lo, int hi, int target, unordered_map<int,int>& memo) -> int {
                    
                    if (lo > hi) return hi + 1;
                    if (response_at(hi, memo) > target) return hi + 1;
                    int l = lo, r = hi;
                    while (l < r) {
                        int m = l + (r - l) / 2;
                        if (response_at(m, memo) <= target) r = m;
                        else l = m + 1;
                    }
                    return l;
                };

                auto interval_for_reply = [&](int replyVal, unordered_map<int,int>& memo) -> ReplyChoice {
                    ReplyChoice rc;
                    rc.reply = replyVal;

                    int curL = feasible.L, curR = feasible.R;
                    if (replyVal == 0) {
                        int r = min(curR, maxa - 1);
                        rc.newL = curL;
                        rc.newR = r;
                        return rc;
                    }

                    if (curR < maxa) {
                        rc.newL = 1; rc.newR = 0;
                        return rc;
                    }
                    int lo0 = max(curL, maxa), hi0 = curR;

                    
                    int lines_lo = response_at(lo0, memo);
                    int lines_hi = response_at(hi0, memo);
                    if (lines_lo < replyVal || lines_hi > replyVal) { 
                        rc.newL = 1; rc.newR = 0;
                        return rc;
                    }

                    int left = first_width_leq_lines(lo0, hi0, replyVal, memo);
                    if (left == hi0 + 1) {
                        rc.newL = 1; rc.newR = 0;
                        return rc;
                    }

                    int right = hi0;
                    if (replyVal > 1) {
                        int t2 = first_width_leq_lines(lo0, hi0, replyVal - 1, memo);
                        if (t2 != hi0 + 1) right = t2 - 1;
                    }

                    rc.newL = max(lo0, left);
                    rc.newR = min(hi0, right);
                    return rc;
                };

                ReplyChoice best;
                best.reply = 0;
                best.newL = 1;
                best.newR = 0;

                unordered_map<int,int> memo;
                memo.reserve(512);

                
                const int range_len = feasible.R - feasible.L + 1;
                const int small_scan_threshold = 2000;
                bool used_exact = false;
                if (range_len <= small_scan_threshold) {
                    int curL = feasible.L, curR = feasible.R;
                    int bestLen = -1;
                    int bestReply = 0;
                    int bestSegL = curL, bestSegR = curL - 1;

                    int segL = curL;
                    int prev = response_at(curL, memo);
                    for (int w = curL + 1; w <= curR; w++) {
                        int cur = response_at(w, memo);
                        if (cur != prev) {
                            int segR = w - 1;
                            int len = segR - segL + 1;
                            if (len > bestLen ||
                                (len == bestLen && (segL < bestSegL ||
                                                    (segL == bestSegL && segR > bestSegR) ||
                                                    (segL == bestSegL && segR == bestSegR && prev < bestReply)))) {
                                bestLen = len;
                                bestReply = prev;
                                bestSegL = segL;
                                bestSegR = segR;
                            }
                            segL = w;
                            prev = cur;
                        }
                    }
                    {
                        int segR = curR;
                        int len = segR - segL + 1;
                        if (len > bestLen ||
                            (len == bestLen && (segL < bestSegL ||
                                                (segL == bestSegL && segR > bestSegR) ||
                                                (segL == bestSegL && segR == bestSegR && prev < bestReply)))) {
                            bestLen = len;
                            bestReply = prev;
                            bestSegL = segL;
                            bestSegR = segR;
                        }
                    }

                    best.reply = bestReply;
                    best.newL = bestSegL;
                    best.newR = bestSegR;
                    used_exact = true;
                }

                if (!used_exact) {
                    
                    vector<int> widths;
                    widths.reserve(8);
                    int curL = feasible.L, curR = feasible.R;
                    auto addW = [&](int w) {
                        if (w < curL || w > curR) return;
                        widths.push_back(w);
                    };
                    addW(curL);
                    addW(curR);
                    addW(curL + (curR - curL) / 2);
                    addW(curL + (curR - curL) / 4);
                    addW(curL + (curR - curL) * 3 / 4);
                    addW(maxa);
                    addW(maxa - 1);

                    sort(widths.begin(), widths.end());
                    widths.erase(unique(widths.begin(), widths.end()), widths.end());

                    vector<int> candidateReplies;
                    candidateReplies.reserve(widths.size() + 1);

                    
                    if (feasible.L <= maxa - 1 && feasible.R >= feasible.L) candidateReplies.push_back(0);

                    for (int w : widths) {
                        int r = response_at(w, memo);
                        candidateReplies.push_back(r);
                    }
                    sort(candidateReplies.begin(), candidateReplies.end());
                    candidateReplies.erase(unique(candidateReplies.begin(), candidateReplies.end()), candidateReplies.end());

                    auto better = [&](const ReplyChoice& A, const ReplyChoice& B) -> bool {
                        
                        int asz = A.size(), bsz = B.size();
                        if (asz != bsz) return asz > bsz;
                        if (A.newL != B.newL) return A.newL < B.newL;
                        if (A.newR != B.newR) return A.newR > B.newR;
                        return A.reply < B.reply;
                    };

                    for (int r : candidateReplies) {
                        ReplyChoice rc = interval_for_reply(r, memo);
                        if (rc.size() <= 0) continue;
                        if (best.size() <= 0 || better(rc, best)) best = rc;
                    }

                    
                    if (best.size() <= 0) {
                        
                        int r = response_at(feasible.L, memo);
                        best = interval_for_reply(r, memo);
                        if (best.size() <= 0) finish(_pe, "internal: could not maintain non-empty feasible set");
                    }
                }

                feasible.L = best.newL;
                feasible.R = best.newR;

                cout << best.reply << "\n";
                cout.flush();
            } else if (tok == "!") {
                long long ansll;
                if (!read_ll(ansll)) finish(_pe, "missing W after '!'");
                if (ansll < 1 || ansll > 100000) finish(_pe, "reported W out of range");
                int ans = (int)ansll;

                if (ans < feasible.L || ans > feasible.R) {
                    finish(_wa, "answer not consistent with interaction");
                }
                if (feasible.L != feasible.R || feasible.L != ans) {
                    finish(_wa, "answer not uniquely determined by interaction");
                }
                break; 
            } else {
                finish(_pe, "invalid command token (expected '?' or '!')");
            }
        }
    }

    
    string extra;
    if (cin >> extra) finish(_pe, "extra output after all test cases");

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


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

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

static int pickStructuredW(long long seed, int minW, int maxW) {
    if (minW == maxW) return minW;

    if (seed == 1) return minW;                 
    if (seed == 2) return maxW;                 
    if (seed == 3) return min(maxW, minW + 1);  

    int span = maxW - minW;

    int roll = rnd.next(1, 100);
    long long w = -1;

    if (roll <= 18) {
        w = (long long)minW + rnd.next(0, min(12, span));
    } else if (roll <= 36) {
        w = (long long)maxW - rnd.next(0, min(12, span));
    } else if (roll <= 68) {
        int mid = minW + (maxW - minW) / 2;
        int delta = rnd.next(-2500, 2500);
        w = (long long)mid + delta;
    } else if (roll <= 86) {
        vector<int> cand;
        for (int p = 0; p <= 17; p++) {
            int base = 1 << p;
            for (int d : {-2, -1, 0, 1, 2}) {
                long long v = (long long)base + d;
                if (v >= minW && v <= maxW) cand.push_back((int)v);
            }
        }
        for (int p = 0; p <= 17; p++) {
            int base = (1 << p) - 1;
            for (int d : {-2, -1, 0, 1, 2}) {
                long long v = (long long)base + d;
                if (v >= minW && v <= maxW) cand.push_back((int)v);
            }
        }
        if (!cand.empty()) {
            w = cand[rnd.next(0, (int)cand.size() - 1)];
        } else {
            w = rnd.next(minW, maxW);
        }
    } else {
        w = rnd.next(minW, maxW);
    }

    return clampInt(w, minW, maxW);
}

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

    string mode = opt<string>("mode", "non");
    int minW = opt<int>("minW", 1);
    int maxW = opt<int>("maxW", 100000);

    if (minW < 1) minW = 1;
    if (maxW > 100000) maxW = 100000;
    if (minW > maxW) swap(minW, maxW);

    long long seed = 1;
    if (argc >= 2) {
        seed = atoll(argv[1]);
        if (seed == 0) seed = 1;
    }

    cout << 1 << "\n";

    if (mode == "non") {
        int W = pickStructuredW(seed, minW, maxW);
        cout << W << "\n";
        return 0;
    }

    if (mode == "adp") {
        int L = minW, R = maxW;

        if (L == R) {
            
        } else if (seed == 1) {
            L = R = minW;
        } else if (seed == 2) {
            L = R = maxW;
        } else if (seed == 3) {
            L = minW;
            R = min(maxW, minW + 1);
        } else {
            
            L = minW;
            R = maxW;
        }

        cout << L << " " << R << "\n";
        return 0;
    }

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