Problem: cf2159_f
Difficulty: medium
Categories: data structures, search
Time limit: 4000 ms, memory limit: 512 MB

This is an interactive problem.

You are given an integer $n$ and an $n\times n$ grid of numbers $G$. The grid of numbers contains each number from $1$ to $n^2$ exactly once.

Let's define a snake of length $l$ as a deque $[(x_1,y_1), (x_2,y_2), \ldots, (x_l,y_l)]$, where $(x_1,y_1)$ is the head of the snake, and $(x_l,y_l)$ is the tail. At second $1$, $x_1=x_2=\ldots = x_l=1$ and $y_i=i$ for all $1 \leq i \leq l$. In other words, the snake is entirely located in the first row, with the head at $(1,1)$ and the rest of the snake to the right of the head.

Each subsequent second, the snake moves down or right in the grid. Formally, the tail $(x_l,y_l)$ is removed, and either $(x_1+1,y_1)$ or $(x_1,y_1+1)$ is added as the new head. The first move of the snake is always downwards. It can be shown that the snake will never intersect itself under these restrictions. The snake will move exactly $2n-2$ times, never moving outside the grid. At second $2n-1$, the head reaches $(n,n)$, and the movement stops. It can be shown that the snake moves exactly $n-1$ times to the right and exactly $n-1$ times downwards.

There are $n$ hidden snakes, with the $i$-th snake having length $i$ for $1 \leq i \leq n$, each moving independently according to the rule above. You do not know how the snakes move. Define $f(l,T)$ as the maximum number that the snake with length $l$ covers at second $T$.

 ![](https://espresso.codeforces.com/5c2b21f2a8715336ccaa0374a0167cebcd4db0a3.gif) An example of a snake with length $l=3$. 

Now, you are also given an integer $m$. Your task is to find the $m$ smallest values of $f(l,T)$, using at most $120n+m$ queries asking for the value of $f(l,T)$ for some $1 \leq l \leq n$ and $1 \leq T \leq 2n-1$.

Input

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

The first line of each test case contains two integers $n$ and $m$ ($2 \leq n \leq 500, 1 \leq m \leq n(2n-1)$).

The following $n$ lines contain the grid $G$. The $i$-th of these lines contains $n$ integers $G_{i,1}, G_{i,2}, \ldots, G_{i,n}$ ($1 \leq G_{i,j} \leq n^2$).

It is guaranteed that $G$ contains each number from $1$ to $n^2$ exactly once.

It is guaranteed that the sum of $n$ over all test cases does not exceed $500$, and the sum of $m$ over all test cases does not exceed $5\cdot 10^4$.

After you read the $n+1$ lines of input, the interaction begins with your first query.

Interaction

To make a query, output a line in the following format (without the quotes):

* "? $l\;T$" ($1 \leq l \leq n$, $1 \leq T \leq 2n-1$).

After each query, read in a single integer – the value of $f(l,T)$. You may ask at most $120n+m$ queries of this type.

When you are ready to output the answer, print a line in the following format:

* "! $S_1\;S_2\;S_3\;\ldots\;S_m$" ($1 \leq S_1 \leq S_2 \leq \ldots \leq S_m$).

This should contain the $m$ smallest values of $f(l,T)$ in non-decreasing order. Note that this does not count towards the query limit.

After this, proceed to the next test case, or exit if this is the last test case.

If you make more than $120n+m$ queries during an interaction, your program must terminate immediately, and you will receive the Wrong Answer verdict. Otherwise, you can get an arbitrary verdict because your solution will continue to read from a closed stream.

After printing each line, do not forget to output the end of line and flush the output buffer. Otherwise, you will receive the Idleness Limit Exceeded verdict. To flush, use:

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

Example

Input

```
1
3 15
4 2 5
1 9 3
7 6 8

4

1

9

6

8

4

4

7

7

8

5

4

9

9

9
```

Output

```
? 1 1

? 1 2

? 1 3

? 1 4

? 1 5

? 2 1

? 2 2

? 2 3

? 2 4

? 2 5

? 3 1

? 3 2

? 3 3

? 3 4

? 3 5

! 1 4 4 4 4 5 6 7 7 8 8 9 9 9 9
```

Note

Below shows the tiles that the three snakes cover as they move across the grid.

 ![](https://espresso.codeforces.com/ae265aa3396b153d344d15880077f08b316cb1a9.gif) The tiles covered by the first snake.  ![](https://espresso.codeforces.com/f7a74347bd76ae802da45d66882bd4c957738d19.gif) The tiles covered by the second snake. 

The tiles covered by the third snake are shown in the statement above.

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;


static long long current_queries = 0;
static long long current_limit = 0;



void log_metrics() {
    try {
        tout << "queries=" << current_queries << endl;
        tout << "query_limit=" << current_limit << endl;
    } catch (...) {
        
    }
}


void finish_verdict(TResult v, string msg) {
    log_metrics();
    quitf(v, "%s", msg.c_str());
}



vector<int> get_sliding_max(const vector<int>& vals, int window_size) {
    vector<int> res;
    deque<int> dq; 
    for (int i = 0; i < (int)vals.size(); ++i) {
        
        if (!dq.empty() && dq.front() <= i - window_size) dq.pop_front();
        
        
        while (!dq.empty() && vals[dq.back()] <= vals[i]) dq.pop_back();
        
        dq.push_back(i);
        
        
        if (i >= window_size - 1) {
            res.push_back(vals[dq.front()]);
        }
    }
    return res;
}

void solve() {
    
    int n = inf.readInt(2, 500, "n");
    
    long long m = inf.readLong(1LL, (long long)n * (2 * n - 1), "m");
    
    
    current_queries = 0;
    current_limit = 120LL * n + m;
    log_metrics();

    
    vector<vector<int>> G(n + 1, vector<int>(n + 1));
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            G[i][j] = inf.readInt(1, n * n, "G_ij");
        }
    }

    
    
    
    
    vector<string> paths(n + 1);
    for (int i = 1; i <= n; ++i) {
        paths[i] = inf.readToken("[DR]+", "path");
    }

    
    
    
    
    cout << n << " " << m << endl;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cout << G[i][j] << (j == n ? "" : " ");
        }
        cout << endl;
    }
    cout.flush();

    
    
    
    
    vector<vector<int>> answers(n + 1, vector<int>(2 * n));
    vector<int> all_values;
    all_values.reserve(n * (2 * n));

    for (int l = 1; l <= n; ++l) {
        
        
        
        vector<int> stream;
        stream.reserve(l + 2 * n);

        
        for (int c = l; c >= 1; --c) {
            stream.push_back(G[1][c]);
        }

        
        int r = 1, c = 1;
        for (char move : paths[l]) {
            if (move == 'D') r++;
            else c++;
            stream.push_back(G[r][c]);
        }

        
        
        
        vector<int> maxs = get_sliding_max(stream, l);
        
        for (int k = 0; k < (int)maxs.size(); ++k) {
            int T = k + 1;
            if (T < 2 * n) { 
                answers[l][T] = maxs[k];
                all_values.push_back(maxs[k]);
            }
        }
    }

    
    sort(all_values.begin(), all_values.end());
    vector<int> expected_ans;
    for (int i = 0; i < m; ++i) {
        expected_ans.push_back(all_values[i]);
    }

    
    while (true) {
        string token;
        if (!(cin >> token)) {
            finish_verdict(_wa, "Unexpected end of input from solution");
        }

        if (token == "!") {
            
            vector<int> user_ans;
            for (int i = 0; i < m; ++i) {
                int val;
                if (!(cin >> val)) finish_verdict(_wa, "Cannot read answer value");
                user_ans.push_back(val);
            }
            
            
            for (size_t i = 1; i < user_ans.size(); ++i) {
                if (user_ans[i] < user_ans[i-1]) {
                    finish_verdict(_wa, "Answer sequence must be non-decreasing");
                }
            }
            
            
            if (user_ans != expected_ans) {
                finish_verdict(_wa, "Wrong answer values");
            }
            
            
            return;
        } else {
            
            
            int l_in, t_in;
            bool valid_syntax = false;

            if (token == "?") {
                if (cin >> l_in >> t_in) valid_syntax = true;
            } else {
                try {
                    l_in = stoi(token);
                    if (cin >> t_in) valid_syntax = true;
                } catch (...) {
                    finish_verdict(_wa, "Invalid query token: " + token);
                }
            }

            if (!valid_syntax) finish_verdict(_wa, "Cannot read query parameters");

            
            current_queries++;
            
            if (current_queries % 2000 == 0) log_metrics();

            if (current_queries > current_limit) {
                finish_verdict(_wa, "Query limit exceeded");
            }

            
            if (l_in < 1 || l_in > n || t_in < 1 || t_in > 2 * n - 1) {
                finish_verdict(_wa, "Query parameters out of range");
            }

            
            cout << answers[l_in][t_in] << endl;
        }
    }
}

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

    
    int t = inf.readInt(1, 100, "t");
    
    
    cout << t << endl;
    cout.flush();

    
    for (int i = 0; i < t; ++i) {
        solve();
    }

    finish_verdict(_ok, "All test cases passed");
    return 0;
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>

using namespace std;


static long long total_queries = 0;
static long long total_query_limit = 0;
static const long long HARD_CAP = 500000;


void log_metrics() {
    
    try {
        tout << "queries=" << total_queries << endl;
        tout << "query_limit=" << total_query_limit << endl;
    } catch (...) {}
}


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


bool is_path_str(const string& s) {
    if (s.empty()) return false;
    for (char c : s) {
        if (c != 'D' && c != 'R') return false;
    }
    return true;
}



string generate_path_adaptive(int n) {
    if (n == 2) return "DR";
    string s = "D";
    
    string suffix = "";
    for (int i = 0; i < n - 2; ++i) suffix += 'D';
    for (int i = 0; i < n - 1; ++i) suffix += 'R';
    
    
    if (!suffix.empty()) {
        for (int i = (int)suffix.size() - 1; i > 0; --i) {
            int j = rnd.next(i + 1);
            swap(suffix[i], suffix[j]);
        }
    }
    return s + suffix;
}



vector<int> get_all_values(int n, int m, const vector<vector<int>>& grid, const vector<string>& paths) {
    vector<int> all_vals;
    all_vals.reserve(n * (2 * n));

    
    for (int l = 1; l <= n; ++l) {
        const string& P = paths[l]; 
        
        
        
        
        
        
        
        
        
        
        int start_k = 2 - l;
        int end_k = 2 * n - 1;
        int len_seq = end_k - start_k + 1;
        
        vector<int> V(len_seq);
        
        
        for (int k = min(1, end_k); k >= start_k; --k) {
            int idx = k - start_k;
            V[idx] = grid[0][1 - k]; 
        }
        
        
        if (end_k > 1) {
            int curr_r = 0, curr_c = 0; 
            for (int k = 2; k <= end_k; ++k) {
                char move = P[k - 2];
                if (move == 'D') curr_r++;
                else curr_c++;
                
                if (k >= start_k) {
                    int idx = k - start_k;
                    V[idx] = grid[curr_r][curr_c];
                }
            }
        }
        
        
        deque<int> dq;
        
        for (int i = 0; i < l; ++i) {
            while (!dq.empty() && V[dq.back()] <= V[i]) dq.pop_back();
            dq.push_back(i);
        }
        all_vals.push_back(V[dq.front()]);
        
        
        
        
        
        
        for (int i = l; i < (int)V.size(); ++i) {
            if (!dq.empty() && dq.front() <= i - l) dq.pop_front();
            while (!dq.empty() && V[dq.back()] <= V[i]) dq.pop_back();
            dq.push_back(i);
            all_vals.push_back(V[dq.front()]);
        }
    }
    return all_vals;
}

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

    int t = inf.readInt();
    cout << t << endl;

    
    string saved_token = "";
    bool has_saved = false;

    for (int test_idx = 0; test_idx < t; ++test_idx) {
        int n;
        if (has_saved) {
            n = stoi(saved_token);
            saved_token = "";
            has_saved = false;
        } else {
            n = inf.readInt();
        }
        
        long long m = inf.readLong();
        
        
        total_query_limit += (120LL * n + m);
        log_metrics(); 
        
        
        cout << n << " " << m << endl;
        
        vector<vector<int>> grid(n, vector<int>(n));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                grid[i][j] = inf.readInt();
                cout << grid[i][j] << (j == n - 1 ? "" : " ");
            }
            cout << endl;
        }
        cout.flush(); 
        
        
        
        
        if (inf.seekEof()) {
            
        } else {
            string tok = inf.readToken();
            if (is_path_str(tok)) {
                
                
                for (int i = 1; i < n; ++i) {
                    inf.readToken();
                }
            } else {
                
                saved_token = tok;
                has_saved = true;
            }
        }
        
        
        
        
        vector<string> snake_paths(n + 1);
        for (int i = 1; i <= n; ++i) {
            snake_paths[i] = generate_path_adaptive(n);
        }
        
        
        vector<int> all_f = get_all_values(n, m, grid, snake_paths);
        sort(all_f.begin(), all_f.end());
        
        bool case_active = true;
        long long queries_this_case = 0;
        long long limit_this_case = 120LL * n + m;
        
        while (case_active) {
            char type;
            if (!(cin >> type)) {
                finish(_wa, "Unexpected EOF from solution");
            }
            
            if (type == '?') {
                int l, T;
                if (!(cin >> l >> T)) finish(_wa, "Invalid query format");
                
                total_queries++;
                queries_this_case++;
                
                
                if (total_queries % 1000 == 0) log_metrics();
                
                
                if (queries_this_case > limit_this_case) {
                    
                    finish(_wa, "Query limit exceeded for this test case");
                }
                if (total_queries > HARD_CAP) {
                    finish(_pe, "Hard query limit exceeded (infinite loop?)");
                }
                
                if (l < 1 || l > n || T < 1 || T > 2 * n - 1) {
                    finish(_wa, "Query parameters out of range");
                }
                
                
                
                const string& P = snake_paths[l];
                int max_val = -1;
                
                int start_k = T - l + 1;
                int end_k = T;
                
                
                for (int k = start_k; k <= min(end_k, 1); ++k) {
                    int val = grid[0][1 - k];
                    if (val > max_val) max_val = val;
                }
                
                
                if (end_k > 1) {
                    int curr_r = 0, curr_c = 0;
                    for (int k = 2; k <= end_k; ++k) {
                        char move = P[k - 2];
                        if (move == 'D') curr_r++; else curr_c++;
                        if (k >= start_k) {
                            int val = grid[curr_r][curr_c];
                            if (val > max_val) max_val = val;
                        }
                    }
                }
                
                cout << max_val << endl;
                
            } else if (type == '!') {
                
                vector<int> user_ans(m);
                for (int i = 0; i < m; ++i) {
                    if (!(cin >> user_ans[i])) finish(_wa, "Failed to read output values");
                }
                
                
                if (all_f.size() < m) finish(_fail, "Internal error: not enough values");
                
                for (int i = 0; i < m; ++i) {
                    if (user_ans[i] != all_f[i]) {
                        
                        string msg = "Wrong answer. Expected " + to_string(all_f[i]) + ", found " + to_string(user_ans[i]) + " at index " + to_string(i+1);
                        finish(_wa, msg);
                    }
                }
                
                
                case_active = false;
            } else {
                finish(_wa, "Unknown query type");
            }
        }
    }
    
    finish(_ok, "All test cases passed");
}


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

using namespace std;








string generate_path(int n, int type) {
    
    
    
    
    
    
    if (n == 2) return "DR";
    
    string suffix = "";
    int d_rem = n - 2;
    int r_rem = n - 1;
    
    if (type == 0) { 
        for(int i=0; i<d_rem; ++i) suffix += 'D';
        for(int i=0; i<r_rem; ++i) suffix += 'R';
        shuffle(suffix.begin(), suffix.end());
    } else if (type == 1) { 
        for(int i=0; i<d_rem; ++i) suffix += 'D';
        for(int i=0; i<r_rem; ++i) suffix += 'R';
    } else if (type == 2) { 
        for(int i=0; i<r_rem; ++i) suffix += 'R';
        for(int i=0; i<d_rem; ++i) suffix += 'D';
    } else if (type == 3) { 
        int cd = d_rem, cr = r_rem;
        while(cd > 0 || cr > 0) {
            if (cr > 0) { suffix += 'R'; cr--; }
            if (cd > 0) { suffix += 'D'; cd--; }
        }
    }
    return "D" + suffix;
}

int main(int argc, char* argv[]) {
    registerGen(argc, argv, 1);
    
    string mode = opt<string>("mode", "non");
    int p_t = opt<int>("t", -1);
    int p_n = opt<int>("n", -1);
    int p_m = opt<int>("m", -1);
    
    vector<pair<int, long long>> cases;
    long long rem_m = 50000;
    int rem_n_sum = 500;
    
    
    if (p_t != -1) {
        int t = p_t;
        while(t--) {
            int n = (p_n != -1) ? p_n : rnd.next(2, 50);
            long long max_m = (long long)n * (2 * n - 1);
            long long m = (p_m != -1) ? p_m : rnd.next(1LL, min((long long)rem_m, max_m));
            if (p_m == -1 && m > rem_m) m = 1; 
            if (p_m == -1) rem_m -= m;
            cases.push_back({n, m});
        }
    } else if (p_n != -1) {
        int n = p_n;
        long long max_m = (long long)n * (2 * n - 1);
        long long m = (p_m != -1) ? p_m : rnd.next(1LL, max_m);
        cases.push_back({n, m});
    } else {
        int seed = atoi(argv[1]);
        if (seed == 1) {
            cases.push_back({2, 1}); 
        } else if (seed == 2) {
            cases.push_back({500, 100}); 
        } else if (seed == 3) {
            cases.push_back({500, 50000}); 
        } else {
            
            if (rnd.next(2) == 0) { 
                int n = rnd.next(200, 500);
                long long m_lim = min((long long)rem_m, (long long)n * (2 * n - 1));
                cases.push_back({n, rnd.next(1LL, m_lim)});
            } else { 
                while(rem_n_sum >= 2 && rem_m > 0) {
                    int n_high = min(rem_n_sum, 60);
                    if (rem_n_sum >= 100 && rnd.next(4) == 0) n_high = min(rem_n_sum, 200);
                    
                    int n = rnd.next(2, n_high);
                    
                    long long max_m = (long long)n * (2 * n - 1);
                    long long m_lim = min((long long)rem_m, max_m);
                    if (m_lim < 1) m_lim = 1;
                    
                    long long m;
                    if (rnd.next(2) == 0) m = rnd.next(1LL, min(m_lim, 200LL));
                    else m = rnd.next(1LL, m_lim);
                    
                    rem_n_sum -= n;
                    rem_m -= m;
                    
                    cases.push_back({n, m});
                    if (rnd.next(15) == 0) break;
                }
            }
        }
    }
    
    println(cases.size());
    for(auto& tc : cases) {
        int n = tc.first;
        long long m = tc.second;
        println(n, m);
        
        
        vector<int> g(n * n);
        iota(g.begin(), g.end(), 1);
        int g_type = rnd.next(100);
        if (g_type < 70) shuffle(g.begin(), g.end());
        else if (g_type < 80) {} 
        else if (g_type < 90) reverse(g.begin(), g.end());
        else { 
             for(int k=0; k<n*n/5; ++k) swap(g[rnd.next(n*n)], g[rnd.next(n*n)]);
        }
        
        for(int i=0; i<n; ++i) {
            for(int j=0; j<n; ++j) {
                cout << g[i*n + j] << (j == n - 1 ? "" : " ");
            }
            cout << "\n";
        }
        
        
        if (mode == "non") {
            int p_strat = rnd.next(5);
            string fixed_p = generate_path(n, 0);
            for(int i=1; i<=n; ++i) {
                if (p_strat == 0) println(generate_path(n, 0)); 
                else if (p_strat == 1) println(fixed_p); 
                else if (p_strat == 2) println(generate_path(n, (i%2)+1)); 
                else if (p_strat == 3) println(generate_path(n, 1)); 
                else println(generate_path(n, 2)); 
            }
        }
    }
    return 0;
}