Problem: cf1761_g
Difficulty: medium
Categories: graph, math
Time limit: 4000 ms, memory limit: 512 MB

This in an interactive problem.

There is an unknown tree consisting of $n$ nodes, which has exactly one centroid. You only know $n$ at first, and your task is to find the centroid of the tree.

You can ask the distance between any two vertices for at most $2\cdot10^5$ times.

Note that the interactor is not adaptive. That is, the tree is fixed in each test beforehand and does not depend on your queries.

A vertex is called a centroid if its removal splits the tree into subtrees with at most $\lfloor\frac{n}{2}\rfloor$ vertices each.

Input

The only line of the input contains an integer $n$ ($3\le n\le 7.5\cdot10^4$) — the number of nodes in the tree.

Interaction

Start interaction by reading $n$.

To ask a query about the distance between two nodes $u, v$ ($1 \le u, v \le n$), output "? u v".

If you determine that the centroid of the tree is $x$, use "! x" to report.

After printing a query, do not forget to output the end of a 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's guaranteed that there are at most $500$ tests in this problem.

Example

Input

```
5

2

1

2

3

1

1

1
```

Output

```
? 1 2

? 1 3

? 1 4

? 1 5

? 2 3

? 3 4

? 4 5

! 3
```

Note

Here is an image of the tree from the sample.

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

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


const int MAXN = 80005;
const int LOGN = 18; 


vector<int> adj[MAXN];
int up[MAXN][LOGN];
int dep[MAXN];
int sz[MAXN];
int n;
int centroid = -1;


static long long queries = 0;
static long long query_limit = 200000;


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



void dfs_sz(int u, int p) {
    sz[u] = 1;
    bool is_centroid = true;
    for (int v : adj[u]) {
        if (v == p) continue;
        dfs_sz(v, u);
        sz[u] += sz[v];
        if (sz[v] > n / 2) is_centroid = false;
    }
    
    if (n - sz[u] > n / 2) is_centroid = false;
    
    if (is_centroid) {
        centroid = u;
    }
}


void dfs_lca(int u, int p, int d) {
    dep[u] = d;
    up[u][0] = p;
    for (int i = 1; i < LOGN; i++) {
        up[u][i] = up[up[u][i-1]][i-1];
    }
    for (int v : adj[u]) {
        if (v != p) dfs_lca(v, u, d + 1);
    }
}


int get_lca(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    for (int i = LOGN - 1; i >= 0; i--) {
        if (dep[u] - (1 << i) >= dep[v]) {
            u = up[u][i];
        }
    }
    if (u == v) return u;
    for (int i = LOGN - 1; i >= 0; i--) {
        if (up[u][i] != up[v][i]) {
            u = up[u][i];
            v = up[v][i];
        }
    }
    return up[u][0];
}


int get_dist(int u, int v) {
    return dep[u] + dep[v] - 2 * dep[get_lca(u, v)];
}

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

    
    n = inf.readInt();
    
    if (n < 3 || n > 75000) {
        
    }

    for (int i = 0; i < n - 1; i++) {
        int u = inf.readInt();
        int v = inf.readInt();
        
        if (u < 1 || u > n || v < 1 || v > n) {
            quitf(_fail, "Invalid edge in test case: %d %d", u, v);
        }
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    
    dfs_sz(1, 0); 
    if (centroid == -1) {
        quitf(_fail, "Internal Error: No centroid found in the provided tree.");
    }
    
    dfs_lca(1, 1, 0); 

    
    cout << n << endl; 

    while (true) {
        string token;
        
        if (!(cin >> token)) {
            finish(_wa, "Unexpected EOF: no answer provided");
        }

        if (token == "!") {
            
            int ans;
            if (!(cin >> ans)) {
                finish(_wa, "Incomplete answer: expected vertex index after '!'");
            }
            
            log_metrics(); 
            if (ans == centroid) {
                quitf(_ok, "Correct! Centroid is %d", ans);
            } else {
                quitf(_wa, "Wrong Answer: expected %d, found %d", centroid, ans);
            }
        } else {
            
            int u, v;
            
            
            if (token == "?") {
                if (!(cin >> u >> v)) {
                    finish(_wa, "Incomplete query: expected two integers after '?'");
                }
            } else {
                
                try {
                    u = stoi(token);
                } catch (...) {
                    finish(_pe, "Protocol Error: expected '?', '!', or integer vertex");
                }
                if (!(cin >> v)) {
                    finish(_wa, "Incomplete query: expected second vertex");
                }
            }

            
            if (u < 1 || u > n || v < 1 || v > n) {
                finish(_wa, format("Invalid query: vertices %d %d out of range [1, %d]", u, v, n));
            }

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

            
            
            if (queries > 250000) {
                finish(_pe, "Hard query limit exceeded (250000)");
            }

            
            int d = get_dist(u, v);
            cout << d << endl;
        }
    }

    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 n_arg = opt<int>("n", -1);
    
    
    int min_n = 3;
    int max_n = 75000;
    
    int n;
    if (n_arg != -1) {
        n = clamp(n_arg, min_n, max_n);
    } else {
        
        long long s = 0;
        try { 
            if (argc > 1) s = stoll(string(argv[1])); 
        } catch(...) {}

        
        if (s == 1) n = 3;
        else if (s == 2) n = 4;
        else if (s == 3) n = 5;
        else if (s == 4) n = max_n;          
        else if (s == 5) n = max_n - 1;      
        else if (s <= 10) n = rnd.next(min_n, 100); 
        else n = rnd.next(min_n, max_n);     
    }
    
    
    
    
    
    
    
    
    
    
    
    
    int rem = n - 1;
    int limit; 
    if (n % 2 == 1) limit = (n - 1) / 2;
    else limit = n / 2 - 1; 
    
    
    vector<int> parts;
    
    
    
    
    
    int strategy = rnd.next(0, 2);
    if (rem < 5) strategy = 2; 
    
    while (rem > 0) {
        int cur_limit = min(rem, limit);
        int sz = 1;
        
        if (strategy == 0) {
            
            
            if (cur_limit > 1 && rnd.next(10) < 7) {
                sz = rnd.next(max(1, cur_limit / 2), cur_limit);
            } else {
                sz = rnd.next(1, cur_limit);
            }
        } else if (strategy == 1) {
            
            int small_cap = max(1, limit / 10);
            sz = rnd.next(1, min(rem, small_cap));
        } else {
            
            sz = rnd.next(1, cur_limit);
        }
        
        parts.push_back(sz);
        rem -= sz;
    }
    
    vector<pair<int, int>> edges;
    
    int current_node_idx = 2;
    
    for (int sz : parts) {
        
        edges.push_back({1, current_node_idx});
        
        
        
        if (sz > 1) {
            vector<int> nodes(sz);
            iota(nodes.begin(), nodes.end(), current_node_idx);
            
            
            int topo = rnd.next(0, 2);
            
            if (topo == 0) {
                
                
                
                vector<int> p = nodes;
                shuffle(p.begin() + 1, p.end());
                
                for (int i = 1; i < sz; i++) {
                    
                    int parent = rnd.next(0, i - 1);
                    edges.push_back({p[i], p[parent]});
                }
            } else if (topo == 1) {
                
                
                vector<int> p = nodes;
                shuffle(p.begin() + 1, p.end());
                for (int i = 0; i < sz - 1; i++) {
                    edges.push_back({p[i], p[i+1]});
                }
            } else {
                
                
                for (int i = 1; i < sz; i++) {
                    edges.push_back({nodes[0], nodes[i]});
                }
            }
        }
        current_node_idx += sz;
    }
    
    
    vector<int> p(n + 1);
    iota(p.begin(), p.end(), 0);
    shuffle(p.begin() + 1, p.end());
    
    
    cout << n << endl;
    for (auto& e : edges) {
        cout << p[e.first] << " " << p[e.second] << endl;
    }
    
    return 0;
}