#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int read() {
  int s = 0;
  char c = getchar(), lc = '+';
  while (c < '0' || '9' < c) lc = c, c = getchar();
  while ('0' <= c && c <= '9') s = s * 10 + c - '0', c = getchar();
  return lc == '-' ? -s : s;
}
void write(int x) {
  if (x < 0) putchar('-'), x = -x;
  if (x < 10)
    putchar(x + '0');
  else
    write(x / 10), putchar(x % 10 + '0');
}
void print(int x, char c = '\n') {
  write(x);
  putchar(c);
}
int n, m, root;
struct edge {
  int to, nxt;
} e[N * 2];
int head[N], cnte = 0;
void add_edge(int u, int v) {
  e[++cnte].to = v;
  e[cnte].nxt = head[u];
  head[u] = cnte;
}
struct BIT {
  int t[N * 2], n;
  void add(int x, int y) {
    for (; x <= n; x += x & -x) t[x] += y;
  }
  int query(int x) {
    int ret = 0;
    for (; x; x = (x - 1) & x) ret += t[x];
    return ret;
  }
} b;
struct LCT {
  struct node {
    int fa, son[2], siz, id, rev_tag;
  } t[N];
  bool isroot(int x) {
    return t[t[x].fa].son[0] != x && t[t[x].fa].son[1] != x;
  }
  bool where(int x) { return t[t[x].fa].son[1] == x; }
  void push_up(int x) {
    t[x].siz = t[t[x].son[0]].siz + t[t[x].son[1]].siz + 1;
  }
  void push_down(int x) {
    if (t[x].rev_tag) {
      swap(t[x].son[0], t[x].son[1]);
      t[t[x].son[0]].rev_tag ^= 1;
      t[t[x].son[1]].rev_tag ^= 1;
      t[x].rev_tag = 0;
    }
  }
  void connect(int x, int y, bool s) { t[x].fa = y, t[y].son[s] = x; }
  void rotate(int x) {
    int y = t[x].fa, R = t[y].fa, wx = where(x), wy = where(y),
        B = t[x].son[!wx];
    if (!isroot(y))
      connect(x, R, wy);
    else
      t[x].fa = R;
    connect(B, y, wx);
    connect(y, x, !wx);
    push_up(y);
    push_up(x);
  }
  void splay(int x) {
    static int st[N], top = 0;
    st[++top] = x;
    for (int tmp = x; !isroot(tmp); tmp = t[tmp].fa) st[++top] = t[tmp].fa;
    while (top) push_down(st[top--]);
    for (; !isroot(x); rotate(x))
      if (!isroot(t[x].fa)) rotate(where(t[x].fa) == where(x) ? t[x].fa : x);
  }
  void access(int x) {
    for (int y = 0; x; y = x, x = t[x].fa) {
      splay(x);
      b.add(t[find(x)].id, t[t[x].son[1]].siz - t[x].siz);
      t[x].son[1] = y;
      push_up(x);
    }
  }
  void make_root(int x) {
    if (root == x) return;
    root = x;
    access(x);
    splay(x);
    t[x].rev_tag ^= 1;
    t[find(x)].id = ++n;
    b.add(n, t[x].siz);
  }
  int find(int x) {
    push_down(x);
    while (t[x].son[1]) x = t[x].son[1], push_down(x);
    return x;
  }
  int query(int x) {
    splay(x);
    return b.query(t[find(x)].id - 1) + t[t[x].son[1]].siz + 1;
  }
} t;
void dfs(int now, int father) {
  b.add(now, 1);
  t.t[now].id = now;
  t.t[now].siz = 1;
  t.t[now].fa = father;
  for (int i = head[now]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to == father) continue;
    dfs(to, now);
  }
}
signed main() {
  root = n = read(), m = read();
  b.n = n + m;
  for (int i = 1; i < n; i++) {
    int u = read(), v = read();
    add_edge(u, v);
    add_edge(v, u);
  }
  dfs(n, 0);
  for (int i = 1; i <= n; i++) {
    t.access(i);
    t.splay(i);
    b.add(i, t.t[i].siz);
  }
  for (int i = 1; i <= m; i++) {
    string opt;
    cin >> opt;
    int u = read(), v = opt == "compare" ? read() : 0;
    if (opt == "up") t.make_root(u);
    if (opt == "when") print(t.query(u));
    if (opt == "compare") print(t.query(u) < t.query(v) ? u : v);
  }
  return 0;
}
