#include<bits/stdc++.h>
#define ff first
#define ss second 
#define pb push_back
#define sz(a) ((int)((a).size()))
#define inf 1e9
using ll = long long;
using ld = long double;
using namespace std;
const int N = 200005;
struct query{
	int a, b, XORab, id, last_node;
};
vector<query>queries;
const int MX = 200000 * 20;
int go[MX][2];
int first[MX];
int lazy[MX];
struct TRIE{
	private: 
		int nxt;
		int generate_node(){
			go[nxt][0] = -1;
			go[nxt][1] = -1;
			first[nxt] = INT_MAX;
			lazy[nxt] = 0;
			return nxt ++ ;
		}
		void propagate(int u, int bit){
			if(lazy[u] == 0)return ;
			if((lazy[u] >> bit) & 1){
				swap(go[u][0], go[u][1]);
			}
			if(go[u][0] != -1){
				lazy[go[u][0]] ^= lazy[u];
			}
			if(go[u][1] != -1){
				lazy[go[u][1]] ^= lazy[u];
			}
			lazy[u] = 0;
		}
		
		int find_maximum(int u, int x, int bit, int &last_node){
			if(bit >= 0){
				propagate(u, bit);
			}
			
			if(bit == -1){
				return 0;
			}
			if((1 << bit) & x){
				// wants 0
				if(go[u][0] != -1 && first[go[u][0]] <= last_node){
					// cout << "move " << 0 << endl;
					return (1 << bit) + find_maximum(go[u][0], x, bit - 1, last_node);
				}else{
					// cout << "move " << 1 << endl;
					return find_maximum(go[u][0], x, bit - 1, last_node);;
				}
			}else{
				// wants 1
				if(go[u][1] != -1 && first[go[u][1]] <= last_node){
					// cout << "move " << 1 << endl;
					return (1 << bit) + find_maximum(go[u][1], x, bit - 1, last_node);
				}else{
					// cout << "move " << 0 << endl;
					return find_maximum(go[u][0], x, bit - 1, last_node);
				}
			}
		}
		void insert_value(int u, int &x, int bit, int &time){
			if(bit >= 0){
				propagate(u, bit);
			}
			first[u] = min(first[u], time);
			if(bit == -1){
		
				return ;
			}
			if((1 << bit) & x){
				if(go[u][1] == -1)go[u][1] = generate_node();
				insert_value(go[u][1], x, bit - 1, time);
			}else{
				if(go[u][0] == -1)go[u][0] = generate_node();
				insert_value(go[u][0], x, bit - 1, time);
			}
		}
	public:
		void reinit (){
			nxt = 1;
			go[0][0] = - 1;
			go[0][1] = -1;
			first[0] = INT_MAX;
			lazy[0] = 0;
			#ifdef LOCAL
			// cout << "reinit " << endl;
			#endif
		}
		int find_maximum(int x, int last_node){
			return find_maximum(0, x, 30, last_node);
		}
		void insert_value(int x, int time){
			insert_value(0, x, 30, time);
			#ifdef LOCAL
			// cout << x << " " << time << " inserted " << endl;
			#endif
		}
		TRIE(){
		}
};
vector<pair<int, int> >adj[N];
vector<query>queries_node[N];
int parent[N];
int parent_weight[N];
int sparse[N][20];
int XOR[N][20];
int depth[N];
int sz[N];
int ans_query[N];
int last_node;
struct LCA{
	
	
	LCA(){
		for(int i = 1 ; i <= last_node ; ++ i){
			sparse[i][0] = parent[i];
			XOR[i][0] = parent_weight[i];
		}
		for(int b = 1 ; b < 20 ; ++ b){
			for(int i = 1 ; i <= last_node ; ++ i){
				sparse[i][b] = sparse[sparse[i][b - 1]][b - 1];
				XOR[i][b] = XOR[sparse[i][b - 1]][b - 1] ^ XOR[i][b - 1];
			}
		}
	}
	int find_xor(int a, int b){
		if(a == b)return 0;
		if(depth[a] < depth[b])swap(a, b);
		// A is deeper
		int distancia = depth[a] - depth[b];
		int ans = 0;
		for(int bit = 19 ; bit >= 0 ; -- bit){
			if((1 << bit) & distancia){
				ans ^= XOR[a][bit];
				a = sparse[a][bit];
			}
		}
		// A is at the same depth as B
		if(a == b)return ans;
		for(int bit = 19 ; bit >= 0 ; -- bit){
			if(sparse[a][bit] == sparse[b][bit])continue;
			ans ^= XOR[a][bit];
			ans ^= XOR[b][bit];
			a = sparse[a][bit];
			b = sparse[b][bit];
		}
		// Subir uno mas
		ans ^= XOR[a][0];
		ans ^= XOR[b][0];
		return ans;
	}
};
void dfs_construct(int u, int d){
	sz[u] = 1;
	depth[u] = d;
	for(auto &c : adj[u]){
		dfs_construct(c.ff, d + 1);
		sz[u] += sz[c.ff];
	}
}
vector<pair<int, int>>distances;
void find_subtree(int u, int x){
	distances.push_back({x, u});
	for(auto &c : adj[u]){
		int v = c.ff;
		int w = c.ss;
		find_subtree(v, x ^ w);
	}
}
TRIE trie;
void dfs_solve(int u, int is_big){
	for(auto &c : adj[u]){
		int v = c.ff;
		int w = c.ss;
		dfs_solve(v, false);
	}
	if(queries_node[u].empty())return ;
	distances.clear();
	find_subtree(u, 0);
	trie.reinit();
	for(int i = 0 ; i < distances.size() ; ++ i){
		trie.insert_value(distances[i].ff, distances[i].ss);
	}
	for(auto &query : queries_node[u]){
		ans_query[query.id] = trie.find_maximum(query.XORab, query.last_node);
	}
}
int main(){
    #ifdef LOCAL
		//freopen("in","r", stdin);
	#endif
	ios_base::sync_with_stdio(0); cin.tie(0);
	int q;
	cin >> q;
	last_node = 1;
	parent[1] = 1;
	for(int i = 0 ; i < q ; ++ i){
		string type ;
		cin >> type;
		if(type == "Add"){
			int x, y;
			cin >> x >> y;
			parent[ ++ last_node] = x;
			parent_weight[last_node] = y;
			adj[x].push_back({last_node , y});
		}else{
			int a, b;
			cin >> a >> b;
			queries.push_back({a, b, -1, i, last_node});
		}
	}
	dfs_construct(1, 0);
	LCA lca;
	for(int i = 0 ; i < queries.size() ; ++ i){
		queries[i].XORab = lca.find_xor(queries[i].a, queries[i].b);
		queries_node[queries[i].b].pb(queries[i]);
	}
	dfs_solve(1, 0);
	for(int i = 0 ; i < queries.size() ; ++ i){
		cout << ans_query[queries[i].id] << "\n";
	}
	
    return 0;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |