Problem: cf1934_c
Difficulty: hard
Categories: math
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem.

You are given a grid with $n$ rows and $m$ columns. The coordinates $(x, y)$ represent the cell on the grid, where $x$ ($1 \leq x \leq n$) is the row number counting from the top and $y$ ($1 \leq y \leq m$) is the column number counting from the left. It is guaranteed that there are exactly $2$ mines in the grid at distinct cells, denoted as $(x_1, y_1)$ and $(x_2, y_2)$. You are allowed to make no more than $4$ queries to the interactor, and after these queries, you need to provide the location of one of the mines.

In each query, you can choose any grid cell $(x, y)$, and in return, you will receive the minimum Manhattan distance from both the mines to the chosen cell, i.e., you will receive the value $\min(|x-x_1|+|y-y_1|, |x-x_2|+|y-y_2|)$.

Your task is to determine the location of one of the mines after making the queries.

Input

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

The only line of each test case contains two integers $n$ and $m$ ($2 \leq n \leq 10^{8}$, $2 \leq m \leq 10^{8}$) — the number of rows and columns.

Interaction

For each test case, the interaction starts with reading $n$ and $m$.

Then you are allowed to make at most $4$ queries in the following way:

"? x y" ($1 \leq x \leq n$ and $1 \leq y \leq m$)

After each one, you should read an integer $d$ which is equal to $\min(|x-x_1|+|y-y_1|, |x-x_2|+|y-y_2|)$.

When you have found the location of any one of the mines, print a single line "! x y" (without quotes), representing the row and the column of one of the mines. Outputting the answer does not count as a query.

After printing the answer, your program must then continue to solve the remaining test cases, or exit if all test cases have been solved.

The interactor for this problem is not adaptive: cells of mines are fixed before any queries are made.

After printing a query, do not forget to output the 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 the documentation for other languages.

Example

Input

```
2
4 4

3

2

2

0

5 5

1

2

3
```

Output

```
? 1 1

? 1 4

? 4 1

? 2 3

! 2 3

? 5 5

? 2 2

? 3 3

! 1 1
```

Note

In the first test case, we start by querying the upper-left corner $(1, 1)$ and get the result $3$, which means that there is a mine on the counter diagonal, and there is no mine above it.

In the image below, each cell contains a number indicating the distance to the blue cell. The green cells are candidates to contain the nearest mine.

 ![](https://espresso.codeforces.com/9960aaa2914a04c86b564f478bbf8b60564bdcce.png) 

Then we ask three cells on that diagonal, and at the last query, we get the result $0$, which means that a mine is found at the position $(2, 3)$.

The second mine was located at the position $(3, 2)$.

In the second test case, we start by asking the lower-right corner $(5, 5)$, and get the result $1$, which means that one of the two neighbours contains a mine, let's call it mine $1$.

 ![](https://espresso.codeforces.com/bbd94711601b9fd8c456dc0d6d9a08fcb7cb46a0.png) 

Then we ask cell $(2, 2)$. We can see that these green cells don't intersect with the green cells from the first query, so they contain the other mine, let's call it mine $2$.

 ![](https://espresso.codeforces.com/5a151386154d24b5ee22c7f21f80d326d80e9be2.png) 

Query $3$ is cell $(3, 3)$. These cells contain mine $1$, but we still don't know where exactly. Nevertheless, we can determine that the only possible cell for mine $2$ is $(1, 1)$, because all other candidates are at a distance closer than $3$ for this query.

 ![](https://espresso.codeforces.com/2380fc8912097b5f4a727cc6ef296e50a7182bca.png)

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


long long dist(long long r1, long long c1, long long r2, long long c2) {
    return std::abs(r1 - r2) + std::abs(c1 - c2);
}

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

    
    int t = inf.readInt();
    
    
    query_limit = 4LL * t;
    
    
    log_metrics();

    
    cout << t << endl;

    for (int i = 0; i < t; ++i) {
        
        
        int n = inf.readInt();
        int m = inf.readInt();
        int x1 = inf.readInt();
        int y1 = inf.readInt();
        int x2 = inf.readInt();
        int y2 = inf.readInt();

        
        cout << n << " " << m << endl;

        
        while (true) {
            
            
            if (queries > max(200000LL, 10 * query_limit)) {
                finish(_pe, "Hard query limit exceeded (infinite loop?)");
            }

            
            string token;
            if (!(cin >> token)) {
                finish(_wa, "Unexpected end of output (expected query or answer)");
            }

            if (token == "!") {
                
                int ax, ay;
                if (!(cin >> ax >> ay)) {
                    finish(_wa, "Cannot read answer coordinates");
                }
                
                
                bool match1 = (ax == x1 && ay == y1);
                bool match2 = (ax == x2 && ay == y2);
                
                if (match1 || match2) {
                    
                    break; 
                } else {
                    finish(_wa, format("Incorrect answer (%d, %d). Mines are at (%d, %d) and (%d, %d).", 
                                       ax, ay, x1, y1, x2, y2));
                }
            } else {
                
                int qx, qy;
                
                
                if (token == "?") {
                    if (!(cin >> qx >> qy)) {
                        finish(_wa, "Cannot read query coordinates after '?'");
                    }
                } else {
                    
                    try {
                        qx = stoi(token);
                    } catch (...) {
                        finish(_wa, format("Invalid token '%s' (expected '?', '!', or integer)", token.c_str()));
                    }
                    if (!(cin >> qy)) {
                        finish(_wa, "Cannot read y-coordinate");
                    }
                }

                
                queries++;
                
                
                if (queries % 10 == 0) log_metrics();

                
                if (qx < 1 || qx > n || qy < 1 || qy > m) {
                    finish(_wa, format("Query (%d, %d) is out of bounds for grid %d x %d", qx, qy, n, m));
                }

                
                long long d1 = dist(qx, qy, x1, y1);
                long long d2 = dist(qx, qy, x2, y2);
                long long ans = min(d1, d2);

                
                cout << ans << endl;
            }
        }
    }

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


Adaptive interactor (C++):

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

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

    
    string mode = opt<string>("mode", "non");
    int seed_val = atoi(argv[1]);
    
    
    
    int t = opt<int>("t", 50);
    if (seed_val <= 5) t = 20;

    println(t);

    for (int i = 0; i < t; ++i) {
        int n, m;

        
        if (seed_val == 1) {
            
            n = rnd.next(2, 8);
            m = rnd.next(2, 8);
        } else if (seed_val == 2) {
            
            if (rnd.next(2)) {
                n = rnd.next(2, 10);
                m = rnd.next(10000, 100000000);
            } else {
                n = rnd.next(10000, 100000000);
                m = rnd.next(2, 10);
            }
        } else if (seed_val == 3) {
            
            n = rnd.next(10000000, 100000000);
            m = rnd.next(10000000, 100000000);
        } else {
            
            int p = rnd.next(100);
            if (p < 20) {
                
                n = rnd.next(2, 20);
                m = rnd.next(2, 20);
            } else if (p < 50) {
                
                if (rnd.next(2)) {
                    n = rnd.next(2, 50);
                    m = rnd.next(1000, 100000000);
                } else {
                    n = rnd.next(1000, 100000000);
                    m = rnd.next(2, 50);
                }
            } else {
                
                n = rnd.next(1000, 100000000);
                m = rnd.next(1000, 100000000);
            }
        }

        if (mode == "adp") {
            
            println(n, m);
        } else {
            
            int x1, y1, x2, y2;
            bool fixed_pattern = false;

            
            if (seed_val <= 3 && i < 2) {
                if (i == 0) {
                    
                    x1 = 1; y1 = 1;
                    x2 = n; y2 = m;
                    fixed_pattern = true;
                } else if (i == 1) {
                    
                    x1 = 1; y1 = m;
                    x2 = n; y2 = 1;
                    fixed_pattern = true;
                }
            }

            if (!fixed_pattern) {
                
                if (rnd.next(100) < 30) {
                    x1 = rnd.next(1, n);
                    y1 = rnd.next(1, m);
                    
                    int dx = rnd.next(-2, 2);
                    int dy = rnd.next(-2, 2);
                    x2 = clamp(x1 + dx, 1, n);
                    y2 = clamp(y1 + dy, 1, m);
                    
                    if (x1 == x2 && y1 == y2) {
                        if (x2 < n) x2++; else x2--;
                    }
                } else {
                    
                    x1 = rnd.next(1, n);
                    y1 = rnd.next(1, m);
                    do {
                        x2 = rnd.next(1, n);
                        y2 = rnd.next(1, m);
                    } while (x1 == x2 && y1 == y2);
                }
            }
            println(n, m, x1, y1, x2, y2);
        }
    }

    return 0;
}