제출 #1196656

#제출 시각아이디문제언어결과실행 시간메모리
1196656APROHACKKlasika (COCI20_klasika)C++20
33 / 110
5053 ms30740 KiB
#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;


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);
	}
}

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);
	}

	distances.clear();
	find_subtree(u, 0);
	for(auto &query : queries_node[u]){
		ans_query[query.id] = 0;
		for(int i = 0 ; i < distances.size() ; ++ i){
			if(distances[i].ss > query.last_node)continue;
			ans_query[query.id] = max(ans_query[query.id], query.XORab ^ distances[i].ff);
		}
	}
}




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 timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...