#include <bits/stdc++.h>
using namespace std;
const int NMAX=1e5;
struct lct {
    struct node {
        int child[2];
        int sum, rev_tag, parent, value;
    };
    node tree[NMAX+5];
    void push(int node) {
        if (tree[node].rev_tag==0) return;
        swap(tree[node].child[0], tree[node].child[1]);
        if (tree[node].child[0]) tree[tree[node].child[0]].rev_tag^=1;
        if (tree[node].child[1]) tree[tree[node].child[1]].rev_tag^=1;
        tree[node].rev_tag=0;
    }
    void pull(int node) {
        tree[node].sum=tree[node].value;
        if (tree[node].child[0]) tree[node].sum+=tree[tree[node].child[0]].sum;
        if (tree[node].child[1]) tree[node].sum+=tree[tree[node].child[1]].sum;
    }
    int get(int node) {
        if (!tree[node].parent) return -1;
        if (node==tree[tree[node].parent].child[0]) return 0;
        if (node==tree[tree[node].parent].child[1]) return 1;
        return -1;
    }
    void rotate(int node) {
        int p = tree[node].parent;
        int pp = tree[p].parent;
        int side1 = get(node);
        int side2 = get(p);
        tree[p].child[side1] = tree[node].child[side1 ^ 1];
        if (tree[p].child[side1]) {
            tree[tree[p].child[side1]].parent = p;
        }
        tree[node].child[side1 ^ 1] = p;
        tree[p].parent = node;
        tree[node].parent = pp;
        if (side2 != -1) tree[pp].child[side2] = node;
        pull(p);
        pull(node);
    }
    void propagate(int node) {
        if (get(node)!=-1) propagate(tree[node].parent);
        push(node);
    }
    void splay(int node) {
        propagate(node);
        while (get(node)!=-1) {
            int side1=get(node);
            int side2=get(tree[node].parent);
            if (side2!=-1) {
                if (side1==side2) {
                    rotate(tree[node].parent);
                }else {
                    rotate(node);
                }
            }
            rotate(node);
        }
    }
    int access(int node) {
        int last=0;
        for (int cur=node;cur;last=cur, cur=tree[cur].parent) {
            splay(cur);
            tree[cur].child[1]=last;
            pull(cur);
        }
        splay(node);
        return last;
    }
    void make_root(int node) {
        access(node);
        tree[node].rev_tag^=1;
    }
    int find_root(int node) {
        access(node);
        while (tree[node].child[0]) {
            push(node);
            node=tree[node].child[0];
        }
        splay(node);
        return node;
    }
    void link_unrooted(int u, int v) {
        if (find_root(u)==find_root(v)) return;
        make_root(u);
        tree[u].parent=v;
    }
    void link_rooted(int u, int v) {
        access(u);
        tree[u].parent = v;
    }
    void cut_unrooted(int u, int v) {
        if (find_root(u)!=find_root(v)) return;
        make_root(u);
        access(v);
        if (tree[v].child[0]==u) {
            tree[v].child[0]=0;
            tree[u].parent=0;
            pull(v);
        }
    }
    void cut_rooted(int u, int v) {
        access(u);
        if (tree[u].child[0]) {
            tree[tree[u].child[0]].parent = 0;
            tree[u].child[0] = 0;
            pull(u);
        }
    }
    int lca(int u, int v) {
        access(u);
        return access(v);
    }
};
lct tree;
int main() {
    int n, m;
    cin>>n>>m;
    for (int i=1;i<=m;i++) {
        string s;
        cin>>s;
        if (s=="lca") {
            int a, b;
            cin>>a>>b;
            cout<<tree.lca(a, b)<<'\n';
        }else if (s=="link") {
            int a, b;
            cin>>a>>b;
            tree.link_rooted(a,b);
        }else {
            int a;
            cin>>a;
            tree.access(a);
            int p=tree.tree[a].child[0];
            if (p) {
                tree.push(p);
                while (tree.tree[p].child[1]) {
                    p=tree.tree[p].child[1];
                    tree.push(p);
                }
                tree.cut_rooted(a, p);
            }
        }
    }
}
