#include
#include
#include
#include
using namespace std;
const int maxn = 3e5 + 10;
int n, LOG;
int id_node[maxn];
int parent[maxn];
int depth[maxn];
int query[maxn];
struct node {
int idx, A, B;
node () {}
node(int _idx, int _A, int _B) {
idx = _idx;
A =_A;
B = _B;
}
};
int up_node[maxn][21];
void up_node_process() {
memset(up_node, -1, sizeof up_node);
for(int i = 0; i <= n; i++) {
up_node[i][0] = parent[i];
}
for(int i = 0; i <= n; i++) {
for(int j = 1; j < LOG; j++) {
up_node[i][j] = up_node[ up_node[i][j - 1] ][j - 1];
}
}
}
int LCA(int A, int B) {
if(depth[A] < depth[B]) {
swap(A, B);
}
for(int i = LOG - 1; i >= 0; i--) {
if(depth[A] - (1 << i) >= depth[B]) {
A = up_node[A][i];
}
}
if(A == B) {
return A;
}
for(int i = LOG - 1; i >= 0; i--) {
if(up_node[A][i] != -1 and up_node[A][i] != up_node[B][i]) {
A = up_node[A][i];
B = up_node[B][i];
}
}
return up_node[A][0];
}
int main() {
ios_base::sync_with_stdio(false);
cin >> n;
LOG = 0;
while((1 << LOG) <= n) {
LOG++;
}
memset(id_node, 0, sizeof id_node);
memset(parent, -1, sizeof parent);
memset(depth, 0, sizeof depth);
memset(query, -1, sizeof query);
parent[0] = 0;
depth[0] = 0;
vector to_LCA;
for(int i = 1; i <= n; i++) {
char c;
cin >> c;
if(c == 'a') {
int A;
cin >> A;
A = id_node[A];
id_node[i] = i;
parent[i] = A;
depth[i] = depth[parent[i]] + 1;
}
else if(c == 'b') {
int A;
cin >> A;
A = id_node[A];
id_node[i] = parent[A];
query[i] = A;
}
else {
int A, B;
cin >> A >> B;
A = id_node[A];
B = id_node[B];
id_node[i] = A;
to_LCA.push_back(node(i, A, B));
}
}
up_node_process();
for(int i = 0; i < (int) to_LCA.size(); i++) {
int A = to_LCA[i].A;
int B = to_LCA[i].B;
int lca = LCA(A, B);
query[to_LCA[i].idx] = depth[lca];
}
for(int i = 1; i <= n; i++) {
if(query[i] != -1) {
cout << query[i] << endl;
}
}
return 0;
}