#ifdef ONLINE_JUDGE #include #else #include #include #include #include #include #include #include #include #include #include #include #include #include #endif using namespace std; // lambda : [] (int a, int b) -> bool { body return } // string r_str = R"(raw string)" #define mp make_pair #define eb emplace_back #define pb push_back #define LL long long #define ULL unsigned long long #define BASE 73 #define NMAX 200001 #define NMAX2 20001 #define MOD1 1000000007 #define ALL(V) (V).begin(), (V).end() #define ALLR(V) (V).rbegin(), (V).rend() #define CRLINE Duxar(__LINE__); #define SHOWME(x) cerr << __LINE__ << ": " << #x << " = " << (x) << endl; #define ENTER putchar('\n'); void Duxar(int _this_line) { #ifndef ONLINE_JUDGE printf("\n . . . . . . . . . . . . . Passed line - %d\n", _this_line); #endif } template void ReadNo(T &_value) { T sign = 1; char ch; _value = 0; while(!isdigit(ch = getchar())) { (ch == '-') && (sign = -1); } do { _value = _value * 10 + (ch - '0'); } while(isdigit(ch = getchar())); _value *= sign; } template void AddNr(T &a, T b) { a = a + b; while (a >= MOD1) { a -= MOD1; } while (a < 0) { a += MOD1; } } int N, Q, current_root = 1, pos_dfs; vector > graph, rmq; vector level(NMAX), euler_nodes(NMAX), first_found, biggest_pw2; void EulerDFS(int c_level, int iam, int from = -1); void PrepareRMQ(); int Query(int x, int y); int GetLCA(int x, int y); int main(){ #ifndef ONLINE_JUDGE freopen("input.cpp", "r", stdin); #endif int i, x, y, t; ReadNo(N); ReadNo(Q); graph.resize(N + 1); first_found.resize(N + 1); for (i = 1; i < N; ++i) { ReadNo(x); ReadNo(y); graph[x].pb(y); graph[y].pb(x); } EulerDFS(0, 1); PrepareRMQ(); for (i = 0; i < Q; ++i) { ReadNo(t); if (t == 1) { ReadNo(current_root); } else { ReadNo(x); ReadNo(y); printf("%d\n", Query(x, y)); } } return 0; } void EulerDFS(int c_level, int iam, int from) { ++pos_dfs; euler_nodes[pos_dfs] = iam; first_found[iam] = pos_dfs; level[pos_dfs] = c_level; for (auto to: graph[iam]) { if (to != from) { EulerDFS(c_level + 1, to, iam); ++pos_dfs; euler_nodes[pos_dfs] = iam; level[pos_dfs] = c_level; } } } void PrepareRMQ() { biggest_pw2.resize(pos_dfs + 1); rmq.resize(18, vector (pos_dfs + 1)); int i, k, lg; rmq[0][1] = 1; for (i = 2; i <= pos_dfs; ++i) { rmq[0][i] = i; biggest_pw2[i] = biggest_pw2[i >> 1] + 1; } for (k = 1; (1 << k) <= pos_dfs; ++k) { lg = 1 << (k - 1); for (i = 1; i + (1 << k) - 1 <= pos_dfs; ++i) { rmq[k][i] = rmq[k - 1][i]; if (level[rmq[k - 1][i + lg]] < level[rmq[k][i]]) { rmq[k][i] = rmq[k - 1][i + lg]; } } } } int GetLCA(int x, int y) { int ans, lg, px, py, p2; px = first_found[x]; py = first_found[y]; if (py < px) swap(px, py); lg = py - px + 1; p2 = biggest_pw2[lg]; ans = rmq[p2][px]; if (level[rmq[p2][py - (1 << p2) + 1]] < level[ans]) { ans = rmq[p2][py - (1 << p2) + 1]; } return ans; } int Query(int x, int y) { int a = GetLCA(x, y); int b = GetLCA(x, current_root); int c = GetLCA(y, current_root); int ans = a; if (level[b] > level[ans]) ans = b; if (level[c] > level[ans]) ans = c; ans = euler_nodes[ans]; if (ans == x || ans == y) { return -1; } return ans; }