#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <cmath>
#include <deque>
#include <iomanip>
#include <stack>
#include <queue>
#include <cstring>
#include <array>
#include <random>
#include <chrono>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define endl '\n'
#define yes cout << "YES\n";
#define no cout << "NO\n";
#define ll int
#define sz(x) (int)x.size()
#define EO(x) (x & 1 ? "ODD" : "EVEN")
#define YN(x) (x ? "YES" : "NO")
#define watch(x) cout << #x << " = " << x << endl
void bad_man()
{
ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
// freopen("input.txt", "r", stdin);
}
struct Node
{
Node *nxt[2];
int cnt;
int mn_time;
Node()
{
cnt = 0;
mn_time = 1e9;
memset(nxt, 0, sizeof nxt);
}
};
struct Trie
{
Node *root;
vector<pair<int, int>> arr;
Trie()
{
arr.clear();
root = new Node;
}
~Trie()
{
delete root;
}
void insert(int x, int time)
{
arr.push_back({x, time});
Node *cur = root;
cur->mn_time = min(cur->mn_time, time);
for (int bit = 31; ~bit; --bit)
{
int b = bool(x & (1ll << bit));
if (!cur->nxt[b])
cur->nxt[b] = new Node();
cur = cur->nxt[b];
cur->cnt++;
cur->mn_time = min(cur->mn_time, time);
}
}
// max XOR with x
int max_xor(int x, int time)
{
Node *cur = root;
if (cur->mn_time > time)
return x;
for (int bit = 31; ~bit; --bit)
{
int b = bool(x & (1ll << bit));
if (cur->nxt[!b] && cur->nxt[!b]->mn_time <= time)
{
x ^= (!b << bit);
cur = cur->nxt[!b];
}
else
{
x ^= (b << bit);
cur = cur->nxt[b];
}
}
return x;
}
};
ll const N = 2e5 + 5;
struct edge
{
int to, w, time;
};
vector<edge> adj[N];
vector<ll> ans;
vector<tuple<int, int, int>> que[N];
ll pref[N], dep[N], par[N][20];
void dfs(int u, int p)
{
dep[u] = dep[p] + 1;
par[u][0] = p;
for (int i = 1; i < 20; ++i)
par[u][i] = par[par[u][i - 1]][i - 1];
for (auto [v, w, time] : adj[u])
{
if (v == p)
continue;
pref[v] = pref[u] ^ w;
dfs(v, u);
}
}
int lca(int u, int v)
{
if (dep[u] < dep[v])
swap(u, v);
for (int i = 19; i >= 0; --i)
{
if (dep[par[u][i]] >= dep[v])
u = par[u][i];
}
if (u == v)
return u;
for (int i = 19; i >= 0; --i)
{
if (par[u][i] != par[v][i])
{
u = par[u][i];
v = par[v][i];
}
}
return par[u][0];
}
Trie trie[N];
void dfs2(int u, int p)
{
for (auto [v, w, time] : adj[u])
{
if (v == p)
continue;
trie[v].insert(pref[v], time);
dfs2(v, u);
if (trie[u].arr.size() < trie[v].arr.size())
swap(trie[u], trie[v]);
for (auto &[x, t] : trie[v].arr)
trie[u].insert(x, t);
}
for (auto &[u2, time, idx] : que[u])
{
ans[idx] = trie[u].max_xor(pref[u2], time);
}
}
void solve()
{
ll q;
cin >> q;
ll cur = 2;
for (int i = 0; i < q; ++i)
{
string t;
cin >> t;
if (t[0] == 'A')
{
int u, v, w;
cin >> u >> w;
v = cur++;
adj[u].push_back({v, w, i});
adj[v].push_back({u, w, i});
}
else
{
int u, v;
cin >> u >> v;
que[v].emplace_back(u, i, ans.size());
ans.push_back(0);
}
}
dfs(1, 0);
trie[1].insert(pref[1], 0);
dfs2(1, 0);
for (auto &i : ans)
cout << i << endl;
for (int i = 0; i < cur; ++i)
trie[i].arr.clear(), trie[i].root = new Node;
}
int main()
{
bad_man();
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}