Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #ifdef DGC
- #include "debug.h"
- #else
- #define debug(...) 9715
- #endif
- typedef long long ll;
- typedef long double ld;
- typedef complex<double> point;
- #define F first
- #define S second
- template<typename T, typename R = T>
- struct lowest_common_ancestor
- {
- vector<vector<pair<int, T>>> adj;
- vector<vector<int>> lca;
- vector<vector<R>> dist;
- vector<int> lvl;
- lowest_common_ancestor(int n) : adj(n), lca(__lg(n-1)+1, vector<int>(n)), dist(__lg(n-1)+1, vector<R>(n)), lvl(n) {}
- void add_edge(int u, int v, T w)
- {
- adj[u].push_back({v, w});
- adj[v].push_back({u, w});
- }
- void build(int r = 0)
- {
- queue<int> q;
- q.push(r);
- lca[0][r] = -1;
- lvl[r] = 0;
- for (int u, v; !q.empty(); )
- {
- u = q.front(); q.pop();
- for (auto &x : adj[u])
- {
- if ((v = x.F) == lca[0][u]) continue;
- q.push(v);
- lca[0][v] = u;
- dist[0][v] = x.S;
- lvl[v] = lvl[u] + 1;
- for (int i = 1, lg = __lg(lvl[v]); i <= lg; i++)
- {
- lca[i][v] = lca[i - 1][lca[i - 1][v]];
- dist[i][v] = dist[i - 1][lca[i - 1][v]] ^ dist[i - 1][v];
- }
- }
- }
- }
- pair<int, R> query(int u, int v)
- {
- if (lvl[v] > lvl[u])
- swap(u, v);
- R D = 0;
- for (int i = __lg(lvl[u]); i >= 0; i--)
- if (lvl[u] - (1 << i) >= lvl[v])
- {
- D ^= dist[i][u];
- u = lca[i][u];
- }
- if (u == v)
- return {u, D}; //u;
- for (int i = __lg(lvl[u]); i >= 0; i--)
- if ((1 << i) <= lvl[u] && lca[i][u] != lca[i][v])
- {
- D ^= dist[i][v] ^ dist[i][u];
- u = lca[i][u];
- v = lca[i][v];
- }
- D ^= dist[0][u] ^ dist[0][v];
- return {lca[0][u], D}; //lca[0][u];
- }
- };
- struct que
- {
- int a, b, t;
- };
- const int inf = numeric_limits<int>::max();
- struct node
- {
- int x, lz;
- node *ch[2];
- node() { x = inf; lz = 0; ch[0]=ch[1]=NULL; }
- };
- void push(node *u)
- {
- if (u && u->lz)
- {
- if (u->lz&1) swap(u->ch[0], u->ch[1]);
- u->lz >>= 1;
- if (u->ch[0]) u->ch[0]->lz ^= u->lz;
- if (u->ch[1]) u->ch[1]->lz ^= u->lz;
- u->lz = 0;
- }
- }
- void update(node *u)
- {
- u->x = inf;
- if (u->ch[0]) u->x = min(u->x, u->ch[0]->x);
- if (u->ch[1]) u->x = min(u->x, u->ch[1]->x);
- }
- void insert(node *u, int b, int x, int t)
- {
- push(u);
- if (b < 0)
- {
- u->x = min(u->x, t);
- return;
- }
- bool d = x>>b&1;
- if (!u->ch[d]) u->ch[d] = new node();
- insert(u->ch[d], b-1, x, t);
- update(u);
- }
- int get(node *u, int x, int t)
- {
- int r = 0;
- for (int i = 30; i >= 0; --i)
- {
- push(u);
- bool d = x>>i&1;
- if (u->ch[!d] && u->ch[!d]->x < t)
- {
- u = u->ch[!d];
- r |= ((int)(!d)) << i;
- }
- else
- {
- u = u->ch[d];
- r |= ((int)(d)) << i;
- }
- }
- return r^x;
- }
- void merge(node *u, node *v, int b)
- {
- push(u); push(v);
- if (b < 0)
- {
- u->x = min(u->x, v->x);
- return;
- }
- if (v->ch[0])
- {
- if (!u->ch[0])
- u->ch[0] = v->ch[0];
- else
- merge(u->ch[0], v->ch[0], b-1);
- }
- if (v->ch[1])
- {
- if (!u->ch[1])
- u->ch[1] = v->ch[1];
- else
- merge(u->ch[1], v->ch[1], b-1);
- }
- update(u);
- }
- int flip(int x)
- {
- int r = 0;
- for (int i = 30; i >= 0; --i)
- r |= (x>>i&1) << (30-i);
- return r;
- }
- int main()
- {
- #ifdef DGC
- //freopen("a.in", "r", stdin);
- //freopen("b.out", "w", stdout);
- #endif
- ios_base::sync_with_stdio(0), cin.tie(0);
- int q;
- cin >> q;
- vector<int> tim(q);
- vector<vector<pair<int, int>>> adj(q);
- vector<vector<que>> qs(q);
- int n = 1, ti = 0;
- for (string s; q--; ++ti)
- {
- int u, v;
- cin >> s >> u >> v;
- if (s[0] == 'A')
- {
- --u;
- adj[u].push_back({ n, v });
- tim[n] = ti;
- ++n;
- }
- else
- {
- --u, --v;
- qs[v].push_back({ u, v, ti });
- }
- }
- lowest_common_ancestor<int> lca(n);
- for (int u = 0; u < n; ++u)
- for (auto v : adj[u])
- lca.add_edge(u, v.F, v.S);
- lca.build();
- vector<node*> roots(n);
- vector<pair<int, int>> ans;
- function<void(int)> dfs = [&](int u)
- {
- roots[u] = new node();
- insert(roots[u], 30, 0, tim[u]);
- for (auto v : adj[u])
- {
- dfs(v.F);
- roots[v.F]->lz ^= flip(v.S);
- merge(roots[u], roots[v.F], 30);
- }
- for (auto &k : qs[u])
- ans.push_back({ k.t, get(roots[u], lca.query(k.a, k.b).S, k.t) });
- };
- dfs(0);
- sort(ans.begin(), ans.end());
- for (auto i : ans)
- cout << i.S << "\n";
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement