Problem: cf1174_f
Difficulty: medium
Categories: graph, search
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive problem.

You're given a tree consisting of $n$ nodes, rooted at node $1$. A tree is a connected graph with no cycles.

We chose a hidden node $x$. In order to find this node, you can ask queries of two types:

* d $u$ ($1 \le u \le n$). We will answer with the distance between nodes $u$ and $x$. The distance between two nodes is the number of edges in the shortest path between them.
* s $u$ ($1 \le u \le n$). We will answer with the second node on the path from $u$ to $x$. However, there's a plot twist. If $u$ is not an ancestor of $x$, you'll receive "Wrong answer" verdict!

Node $a$ is called an ancestor of node $b$ if $a \ne b$ and the shortest path from node $1$ to node $b$ passes through node $a$. Note that in this problem a node is not an ancestor of itself.

Can you find $x$ in no more than $36$ queries? The hidden node is fixed in each test beforehand and does not depend on your queries.

Input

The first line contains the integer $n$ ($2 \le n \le 2 \cdot 10^5$) — the number of nodes in the tree.

Each of the next $n-1$ lines contains two space-separated integers $u$ and $v$ ($1 \le u,v \le n$) that mean there's an edge between nodes $u$ and $v$. It's guaranteed that the given graph is a tree.

Output

To print the answer, print "! x" (without quotes).

Interaction

To ask a question, print it in one of the formats above:

* d $u$ ($1 \le u \le n$), or
* s $u$ ($1 \le u \le n$).

After each question, you should read the answer: either the distance or the second vertex on the path, as mentioned in the legend.

If we answer with $-1$ instead of a valid answer, that means you exceeded the number of queries, made an invalid query, or violated the condition in the second type of queries. Exit immediately after receiving $-1$ and you will see 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 the documentation for other languages.

Example

Input

```
5
1 2
1 3
3 4
3 5
3
5
```

Output

```
d 2
s 3
! 5
```

Note

In the first example, the hidden node is node $5$.

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

We first ask about the distance between node $x$ and node $2$. The answer is $3$, so node $x$ is either $4$ or $5$. We then ask about the second node in the path from node $3$ to node $x$. Note here that node $3$ is an ancestor of node $5$. We receive node $5$ as the answer. Finally, we report that the hidden node is node $5$.

Non-adaptive interactor (C++):






#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;


static long long queries = 0;


static long long query_limit = 36;

static const int HARD_CAP = 100000;


static const int MAXN = 200005;
static const int LOGN = 20;


int n;
vector<int> adj[MAXN];
int hidden_x;



int tin[MAXN], dfs_out[MAXN];
int timer_dfs = 0;
int up[MAXN][LOGN];
int depth[MAXN];




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


static void build_rooted_tree(int root) {
    timer_dfs = 0;

    vector<int> parent(n + 1, 0);
    vector<int> it(n + 1, 0);
    vector<int> st;
    st.reserve(n);

    parent[root] = root;
    depth[root] = 0;
    up[root][0] = root;
    for (int i = 1; i < LOGN; i++) up[root][i] = root;
    tin[root] = ++timer_dfs;
    st.push_back(root);

    while (!st.empty()) {
        int u = st.back();
        if (it[u] < (int)adj[u].size()) {
            int v = adj[u][it[u]++];
            if (v == parent[u]) continue;
            parent[v] = u;
            depth[v] = depth[u] + 1;
            up[v][0] = u;
            for (int i = 1; i < LOGN; i++) {
                up[v][i] = up[up[v][i - 1]][i - 1];
            }
            tin[v] = ++timer_dfs;
            st.push_back(v);
        } else {
            dfs_out[u] = timer_dfs;
            st.pop_back();
        }
    }
}


bool is_ancestor_reflexive(int u, int v) {
    return tin[u] <= tin[v] && dfs_out[u] >= dfs_out[v];
}

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

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

int get_kth_ancestor(int node, int k) {
    for (int i = 0; i < LOGN; i++) {
        if ((k >> i) & 1) {
            node = up[node][i];
        }
    }
    return node;
}

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

    
    n = inf.readInt(2, 200000, "n");
    vector<pair<int, int>> edges;
    for (int i = 0; i < n - 1; i++) {
        int u = inf.readInt(1, n, "u");
        int v = inf.readInt(1, n, "v");
        adj[u].push_back(v);
        adj[v].push_back(u);
        edges.push_back({u, v});
    }
    hidden_x = inf.readInt(1, n, "x");

    
    build_rooted_tree(1); 

    
    cout << n << endl;
    for (auto& e : edges) {
        cout << e.first << " " << e.second << "\n";
    }
    cout.flush();
    
    
    log_metrics();

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

        
        if (token == "?") {
            if (!(cin >> token)) {
                finish(_wa, "Unexpected EOF after '?'");
            }
        }

        
        if (token == "!") {
            int ans;
            if (!(cin >> ans)) finish(_wa, "Unexpected EOF reading answer value");
            
            if (ans == hidden_x) {
                finish(_ok, "Correct answer");
            } else {
                finish(_wa, format("Wrong answer: expected %d, found %d", hidden_x, ans));
            }
        }

        
        if (token != "d" && token != "s") {
            finish(_wa, format("Invalid query token: '%s'", token.c_str()));
        }

        int u;
        if (!(cin >> u)) {
            finish(_wa, "Unexpected EOF reading query parameter");
        }

        
        queries++;
        
        if (queries % 10 == 0) log_metrics();
        
        
        if (queries > HARD_CAP) {
            finish(_pe, "Too many queries (hard cap exceeded)");
        }

        
        if (u < 1 || u > n) {
            finish(_wa, format("Invalid node index: %d", u));
        }

        if (token == "d") {
            
            int d = get_dist(u, hidden_x);
            cout << d << endl;
        } else { 
            
            
            
            
            if (u == hidden_x || !is_ancestor_reflexive(u, hidden_x)) {
                finish(_wa, format("Query 's %d' invalid: %d is not a proper ancestor of hidden node", u, u));
            }

            
            
            
            
            int k = depth[hidden_x] - (depth[u] + 1);
            
            int ans = get_kth_ancestor(hidden_x, k);
            cout << ans << endl;
        }
    }

    return 0;
}


Adaptive interactor (C++):











#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;


const int MAXN = 200005;
const int LOGN = 20;

int n;
vector<int> adj[MAXN];
int up[MAXN][LOGN];

int tin[MAXN], tout_dfs[MAXN];
int depth[MAXN];
int timer_dfs;

vector<int> candidates;
long long queries = 0;
long long query_limit = 36;



static void build_rooted_tree(int root) {
    timer_dfs = 0;

    vector<int> parent(n + 1, 0);
    vector<int> it(n + 1, 0);
    vector<int> st;
    st.reserve(n);

    parent[root] = root;
    depth[root] = 0;
    up[root][0] = root;
    for (int i = 1; i < LOGN; i++) up[root][i] = root;
    tin[root] = ++timer_dfs;
    st.push_back(root);

    while (!st.empty()) {
        int u = st.back();
        if (it[u] < (int)adj[u].size()) {
            int v = adj[u][it[u]++];
            if (v == parent[u]) continue;
            parent[v] = u;
            depth[v] = depth[u] + 1;
            up[v][0] = u;
            for (int i = 1; i < LOGN; i++) {
                up[v][i] = up[up[v][i - 1]][i - 1];
            }
            tin[v] = ++timer_dfs;
            st.push_back(v);
        } else {
            tout_dfs[u] = timer_dfs;
            st.pop_back();
        }
    }
}



bool is_ancestor(int u, int v) {
    return tin[u] <= tin[v] && tout_dfs[u] >= tout_dfs[v];
}

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

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



int get_child_towards(int u, int v) {
    int target_d = depth[u] + 1;
    int temp = v;
    
    for (int i = LOGN - 1; i >= 0; i--) {
        if (depth[temp] - (1 << i) >= target_d) {
            temp = up[temp][i];
        }
    }
    return temp;
}



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

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



int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics); 
    
    
    n = inf.readInt();
    vector<pair<int, int>> edges;
    for(int i = 0; i < n - 1; ++i) {
        int u = inf.readInt();
        int v = inf.readInt();
        edges.push_back({u, v});
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    
    
    
    cout << n << endl;
    for(auto& e : edges) {
        cout << e.first << " " << e.second << endl;
    }
    cout.flush(); 

    
    for(int i = 1; i <= n; ++i) candidates.push_back(i);

    build_rooted_tree(1);

    
    log_metrics();

    
    while (true) {
        string type;
        
        if (!(cin >> type)) {
            
            finish(_wa, "Unexpected EOF: expected query token");
        }

        if (type == "!") {
            int ans;
            if (!(cin >> ans)) finish(_wa, "Unexpected EOF reading answer");
            
            bool possible = false;
            for(int c : candidates) {
                if(c == ans) possible = true;
            }
            
            
            
            
            if (possible && candidates.size() == 1) {
                finish(_ok, "Correct answer");
            } else {
                finish(_wa, "Wrong answer: " + to_string(candidates.size()) + " candidates remained");
            }
            
        } else if (type == "d" || type == "s") {
            int u;
            if (!(cin >> u)) finish(_wa, "Unexpected EOF reading u");
            
            
            if (u < 1 || u > n) {
                cout << -1 << endl;
                finish(_wa, "Invalid node index");
            }

            queries++;
            
            if (queries > query_limit) {
                cout << -1 << endl;
                finish(_wa, "Query limit exceeded");
            }
            
            if (queries % 5 == 0) log_metrics();

            if (type == "d") {
                
                
                map<int, int> counts;
                for(int c : candidates) {
                    counts[get_dist(u, c)]++;
                }
                
                int best_d = -1;
                int max_sz = -1;
                
                
                for(auto const& [d, count] : counts) {
                    if (count > max_sz) {
                        max_sz = count;
                        best_d = d;
                    }
                }
                
                
                cout << best_d << endl;
                
                
                vector<int> next_cand;
                next_cand.reserve(max_sz);
                for(int c : candidates) {
                    if (get_dist(u, c) == best_d) {
                        next_cand.push_back(c);
                    }
                }
                candidates = next_cand;
                
            } else {
                
                
                
                vector<int> invalid_cand;
                
                
                for(int c : candidates) {
                    if (u != c && is_ancestor(u, c)) {
                        
                    } else {
                        invalid_cand.push_back(c);
                    }
                }
                
                if (!invalid_cand.empty()) {
                    
                    
                    candidates = invalid_cand;
                    cout << -1 << endl;
                    finish(_wa, "Invalid query: u is not a strict ancestor of hidden node");
                } else {
                    
                    
                    
                    map<int, int> child_counts;
                    for(int c : candidates) {
                        int child = get_child_towards(u, c);
                        child_counts[child]++;
                    }
                    
                    int best_child = -1;
                    int max_sz = -1;
                    
                    
                    for(auto const& [child, count] : child_counts) {
                        if (count > max_sz) {
                            max_sz = count;
                            best_child = child;
                        }
                    }
                    
                    cout << best_child << endl;
                    
                    vector<int> next_cand;
                    next_cand.reserve(max_sz);
                    for(int c : candidates) {
                        if (get_child_towards(u, c) == best_child) {
                            next_cand.push_back(c);
                        }
                    }
                    candidates = next_cand;
                }
            }

        } else {
            finish(_wa, "Invalid query type");
        }
    }
    
    return 0;
}


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 = opt<int>("n", 200000);
    long long seed = atoll(argv[1]);

    
    
    
    
    
    
    
    
    int type = 0;
    if (seed == 1) {
        n = 10;
        type = 1;
    } else if (seed == 2) {
        type = 2;
    } else if (seed == 3) {
        type = 3;
    } else {
        int strat = (seed % 4);
        if (strat == 0) type = 4;
        else if (strat == 1) type = 5;
        else if (strat == 2) type = 6;
        else type = 2; 
    }

    vector<pair<int, int>> edges;
    int x = -1;

    if (type == 1 || type == 5) { 
        
        
        for (int i = 2; i <= n; i++) {
            int p;
            if (type == 5) {
                int range = min(i - 1, 20);
                p = rnd.next(max(1, i - range), i - 1);
            } else {
                p = rnd.next(1, i - 1);
            }
            edges.push_back({p, i});
        }
        x = rnd.next(2, n);
    } 
    else if (type == 2) { 
        for (int i = 2; i <= n; i++) {
            edges.push_back({i - 1, i});
        }
        x = n; 
    } 
    else if (type == 3) { 
        for (int i = 2; i <= n; i++) {
            edges.push_back({1, i});
        }
        x = rnd.next(2, n);
    } 
    else if (type == 4) { 
        
        for (int i = 2; i <= n; i++) {
            edges.push_back({i / 2, i});
        }
        
        x = rnd.next(n / 2 + 1, n);
    } 
    else if (type == 6) { 
        
        int u = 1;
        int rem = n - 1;
        int next_id = 2;
        
        while (rem > 0) {
            if (rem == 1) {
                edges.push_back({u, next_id});
                u = next_id;
                next_id++;
                rem--;
                break;
            }
            
            
            
            
            
            
            
            int sub_growth = (rem - 2) / 2;
            int heavy_sz = (rem - 1) - sub_growth;
            
            
            int heavy_root = next_id++;
            edges.push_back({u, heavy_root});
            
            
            int cur_h = heavy_root;
            for (int k = 0; k < heavy_sz - 1; k++) {
                edges.push_back({cur_h, next_id});
                cur_h = next_id;
                next_id++;
            }
            
            
            int v = next_id++;
            edges.push_back({u, v});
            u = v;
            
            rem -= (heavy_sz + 1);
        }
        x = u;
    }

    
    vector<int> p(n + 1);
    for (int i = 1; i <= n; i++) p[i] = i;
    shuffle(p.begin() + 2, p.end());

    
    vector<pair<int, int>> final_edges;
    for (auto e : edges) {
        final_edges.push_back({p[e.first], p[e.second]});
    }
    
    
    shuffle(final_edges.begin(), final_edges.end());

    
    if (x != -1) x = p[x];

    
    cout << n << "\n";
    for (auto e : final_edges) {
        cout << e.first << " " << e.second << "\n";
    }

    
    if (mode == "non") {
        cout << x << "\n";
    }

    return 0;
}