#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5 + 10;
int n, q, Begin[maxn], Next[maxn], To[maxn], e, c[maxn], anc[maxn], Root;
bool vis[maxn];
char s[maxn];
struct node {
  int son[2], fa, size, id, lazy;
  bool tag;
} Tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int pos, int val) {
  for (int i = pos; i < maxn; i += lowbit(i)) c[i] += val;
}
inline int query(int pos) {
  int sum = 0;
  for (int i = pos; i > 0; i -= lowbit(i)) sum += c[i];
  return sum;
}
inline void add(int u, int v) {
  To[++e] = v;
  Next[e] = Begin[u];
  Begin[u] = e;
}
inline bool IsRoot(int root) {
  return Tree[Tree[root].fa].son[0] != root &&
         Tree[Tree[root].fa].son[1] != root;
}
inline void PushTag(int root) {
  if (!root) return;
  swap(Tree[root].son[0], Tree[root].son[1]);
  Tree[root].tag ^= 1;
}
inline void Maintain(int root, int val) {
  if (!root) return;
  Tree[root].id = Tree[root].lazy = val;
}
inline void PushDown(int root) {
  if (Tree[root].tag) {
    PushTag(Tree[root].son[0]);
    PushTag(Tree[root].son[1]);
    Tree[root].tag ^= 1;
  }
  if (Tree[root].lazy) {
    Maintain(Tree[root].son[0], Tree[root].lazy);
    Maintain(Tree[root].son[1], Tree[root].lazy);
    Tree[root].lazy = 0;
  }
}
inline void PushUp(int root) {
  Tree[root].size =
      Tree[Tree[root].son[0]].size + Tree[Tree[root].son[1]].size + 1;
}
inline void Get(int root) {
  if (!IsRoot(root)) Get(Tree[root].fa);
  PushDown(root);
}
inline void Rotate(int x) {
  int y = Tree[x].fa, z = Tree[y].fa, k = Tree[y].son[1] == x,
      w = Tree[x].son[!k];
  if (!IsRoot(y)) Tree[z].son[Tree[z].son[1] == y] = x;
  if (w) Tree[w].fa = y;
  Tree[x].fa = z;
  Tree[y].fa = x;
  Tree[x].son[!k] = y;
  Tree[y].son[k] = w;
  PushUp(y);
  PushUp(x);
}
inline void Splay(int x) {
  Get(x);
  while (!IsRoot(x)) {
    int y = Tree[x].fa, z = Tree[y].fa;
    if (!IsRoot(y))
      Rotate((Tree[y].son[0] == x) ^ (Tree[z].son[0] == y) ? x : y);
    Rotate(x);
  }
}
inline void Access(int root) {
  for (int x = 0; root; x = root, root = Tree[root].fa) {
    Splay(root);
    PushDown(root);
    modify(Tree[root].id, -Tree[Tree[root].son[0]].size - 1);
    Tree[root].son[1] = x;
    PushUp(root);
  }
}
inline int ask(int v) {
  Splay(v);
  PushDown(v);
  return Tree[Tree[v].son[1]].size + 1 + query(Tree[v].id - 1);
}
inline void DFS(int u, int fa) {
  anc[u] = fa;
  for (int i = Begin[u]; i; i = Next[i])
    if (To[i] != fa) DFS(To[i], u);
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = (1), _end_ = (n - 1); i <= _end_; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    add(u, v);
    add(v, u);
  }
  DFS(n, 0);
  vis[0] = true;
  for (int i = n; i >= 1; --i)
    if (!vis[i]) {
      int x = i, num = 0;
      while (!vis[x]) {
        vis[x] = true;
        ++num;
        Tree[x].fa = anc[x];
        if (!vis[anc[x]]) Tree[anc[x]].son[1] = x;
        PushUp(x);
        Tree[x].id = i;
        x = anc[x];
      }
      modify(i, num);
    }
  while (q--) {
    scanf("%s", s + 1);
    int u, v;
    if (s[1] == 'u') {
      scanf("%d", &v);
      Access(v);
      Splay(v);
      PushTag(v);
      ++n;
      modify(n, Tree[v].size);
      Maintain(v, n);
      Root = v;
    }
    if (s[1] == 'w') {
      scanf("%d", &v);
      printf("%d\n", ask(v));
    }
    if (s[1] == 'c') {
      scanf("%d%d", &u, &v);
      printf("%d\n", ask(u) < ask(v) ? u : v);
    }
  }
  return 0;
}
