#include <bits/stdc++.h>
constexpr auto MAXN = 200000 + 50;
constexpr auto MAXM = 200000 + 50;
constexpr auto MAXT = MAXN + MAXM;
int bit_array[MAXT];
void Add(int pos, const int& delta) {
  for (; pos > 0 && pos < MAXT; pos += ((pos) & (-(pos))))
    bit_array[pos] += delta;
}
int Query(int pos) {
  int ans = 0;
  for (; pos > 0; pos -= ((pos) & (-(pos)))) ans += bit_array[pos];
  return ans;
}
struct Node {
  bool rev;
  int siz;
  int color;
  bool mark;
  int set;
  Node *ch[2], *up;
  Node() {
    ch[0] = ch[1] = up = nullptr;
    mark = rev = false;
    siz = 1;
    color = 0;
  }
  Node& Reverse(void) {
    rev ^= 1;
    std::swap(ch[0], ch[1]);
    return *this;
  }
  Node& Set(const int& val) {
    mark = true;
    set = color = val;
    return *this;
  }
  Node& Push_Down(void) {
    if (rev) {
      if (ch[0] != nullptr) ch[0]->Reverse();
      if (ch[1] != nullptr) ch[1]->Reverse();
    }
    rev = false;
    if (mark) {
      if (ch[0] != nullptr) ch[0]->Set(set);
      if (ch[1] != nullptr) ch[1]->Set(set);
    }
    mark = false;
    return *this;
  }
  bool IsRoot(void) const {
    if (up == nullptr)
      return true;
    else
      return (up->ch[0] != this && up->ch[1] != this);
  }
  short GetPos(const Node* comp) const {
    if (ch[1] != comp && ch[0] != comp) return -1;
    return ch[1] == comp;
  }
  Node& Update(void) {
    siz = 1;
    if (ch[0] != nullptr) siz += ch[0]->siz;
    if (ch[1] != nullptr) siz += ch[1]->siz;
    return *this;
  }
} node[MAXN];
void Rotate(Node* targ) {
  Node* fa = targ->up;
  const short pos = fa->GetPos(targ);
  fa->ch[pos] = targ->ch[pos ^ 1];
  if (fa->ch[pos] != nullptr) fa->ch[pos]->up = fa;
  if (!fa->IsRoot()) fa->up->ch[fa->up->GetPos(fa)] = targ;
  targ->ch[pos ^ 1] = fa;
  targ->up = fa->up;
  fa->up = targ;
  fa->Update();
  targ->Update();
}
std::stack<Node*> S;
void Spaly(Node* targ) {
  Node* nowAt = targ;
  S.push(nowAt);
  while (!nowAt->IsRoot()) S.push(nowAt = nowAt->up);
  while (!S.empty()) {
    S.top()->Push_Down();
    S.pop();
  }
  for (nowAt = targ; !nowAt->IsRoot() && !nowAt->up->IsRoot(); Rotate(nowAt))
    if (nowAt->up->GetPos(nowAt) == nowAt->up->up->GetPos(nowAt->up))
      Rotate(nowAt->up);
    else
      Rotate(nowAt);
  if (!nowAt->IsRoot()) Rotate(nowAt);
}
void Access(Node* nowAt) {
  for (Node* last = nullptr; nowAt != nullptr; nowAt = nowAt->up) {
    Spaly(nowAt);
    Add(nowAt->color,
        -(nowAt->siz - (nowAt->ch[1] == nullptr ? 0 : nowAt->ch[1]->siz)));
    nowAt->ch[1] = last;
    nowAt->Update();
    last = nowAt;
  }
}
void Make_Root(Node* nowAt) {
  Access(nowAt);
  Spaly(nowAt);
  nowAt->Reverse();
}
std::vector<int> G[MAXN];
bool vis[MAXN];
int nowColor;
Node* last = node + 1;
void Dfs(const int& nowAt = 1) {
  vis[nowAt] = true;
  for (const auto& it : G[nowAt])
    if (!vis[it]) {
      Dfs(it);
      node[it].up = node + nowAt;
    }
}
void Up(Node* targ) {
  Spaly(last);
  assert(last->up == nullptr);
  Make_Root(last = targ);
  targ->Set(++nowColor);
  Add(nowColor, targ->siz);
}
int When(Node* targ) {
  Spaly(targ);
  return Query(targ->color) - (targ->ch[0] == nullptr ? 0 : targ->ch[0]->siz);
}
signed main(void) {
  int totNode, totQuery, targ, a, b;
  char opt[15];
  scanf("%d%d", &totNode, &totQuery);
  for (int i = 1; i < totNode; i++) {
    scanf("%d%d", &a, &b);
    G[a].push_back(b);
    G[b].push_back(a);
  }
  Dfs();
  node[1].up = nullptr;
  for (int i = 1; i <= totNode; i++) Up(node + i);
  while (totQuery--) {
    scanf("%s", opt);
    switch (*opt) {
      case 'w':
        scanf("%d", &targ);
        printf("%d\n", When(node + targ));
        break;
      case 'c':
        scanf("%d%d", &a, &b);
        printf("%d\n", When(node + a) < When(node + b) ? a : b);
        break;
      case 'u':
        scanf("%d", &targ);
        Up(node + targ);
        break;
      default:
        assert(false);
        break;
    }
  }
END:
  return 0;
}
