#include #include #include   using namespace std;   #define MAX_N 100005 #define MAX_L 20   #define foreach(V) for(typeof (V).begin() it = (V).begin(); it != (V).end(); ++it)   int K, N, M; int L[MAX_N << 1], H[MAX_N << 1],Lg[MAX_N << 1], First[MAX_N]; int Rmq[MAX_L][MAX_N << 2]; char viz[MAX_N];  vector G[MAX_N];   ifstream fin ("lca.in"); ofstream fout ("lca.out");   void citire() {     fin >> N >> M;           for(int i = 2; i <= N; ++i)     {         int x, y;         fin >> x >> y;         G[x].push_back(y); G[y].push_back(x);     } }   void dfs(int nod, int lev) {     H[++K] = nod; //nodul actual este adaugat in reprezentarea Euler a arborelui     L[K] = lev; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui     First[nod] = K; //se retine si prima aparitie a fiecarui nod in reprezentarea Euler a arborelui viz[nod] = 1;        foreach(G[nod])     { if (viz[*it] == 0) {          dfs(*it, lev+1);             H[++K] = nod;         L[K] = lev; }     } }   void rmq() { //in Rmq[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui     for(int i = 2; i <= K; ++i)         Lg[i] = Lg[i >> 1] + 1;     for(int i = 1; i <= K; ++i)           for(int i = 1; (1 << i) < K; ++i)         for(int j = 1; j <= K - (1 << i); ++j)         {             int l = 1 << (i - 1);               Rmq[0][i] = i;             Rmq[i][j] = Rmq[i-1][j];             if(L[Rmq[i-1][j + l]] < L[Rmq[i][j]])                 Rmq[i][j] = Rmq[i-1][j + l];         } }   int lca(int x, int y) { //LCA-ul nodurilor x si y va fi nodul cu nivel minim din secventa (First[x], First[y]) din reprezentarea Euler a arborelui     int diff, l, sol, sh;     int a = First[x], b = First[y];     if(a > b) swap(a, b);     diff = b - a + 1;     l = Lg[diff];     sol = Rmq[l][a];     sh = diff - (1 << l);     if(L[sol] > L[Rmq[l][a + sh]])         sol = Rmq[l][a + sh];     return H[sol]; }   int main() { int lastroot = 1;     citire();     dfs(1, 0); // assume 1 is the first root, problem maker is an idiot     rmq();           while(M--)     {         int x, y, z;         fin >> x; if (x == 1) { int newroot; fin >> newroot; if (newroot != lastroot) { lastroot = newroot; memset(viz, 0, N+5); dfs(newroot, 0); rmq(); } } else { fin >> y >> z; int lcayz = lca(y, z); if (lcayz == y || lcayz == z) { fout << -1 << "\n"; } else fout << lcayz << "\n"; }     } return 0; }