Submission #1292676

#TimeUsernameProblemLanguageResultExecution timeMemory
1292676paronmanukyanKlasika (COCI20_klasika)C++20
0 / 110
104 ms68764 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long #define V vector #define rep(a, b, c, d) for (int a = b; a <= c; a += d) #define pii pair<int,int> #define ff first #define ss second #define pb push_back const int N = 200000 + 5; const int BT = 31; struct Node { int ch[2]; int pass; // how many active entries pass through this node V<int> tins[2]; // tins for edges 0/1 from this node Node() { ch[0]=ch[1]=0; pass=0; } }; V<Node> trie; int root = 0; int new_node() { trie.emplace_back(); return (int)trie.size()-1; } void ensure_child(int cur, int bit) { if (!trie[cur].ch[bit]) { int id = new_node(); trie[cur].ch[bit] = id; } } void insert_sorted_vec(V<int> &v, int x) { // insert x keeping v sorted auto it = lower_bound(v.begin(), v.end(), x); v.insert(it, x); } int gch(int cur, int b) { return trie[cur].ch[b]; } int n_nodes = 1; int st[N]; int tin[N], tout[N]; int tm_ = 1; V<int> adj[N]; void dfs(int node) { tin[node] = tm_++; for (int to : adj[node]) dfs(to); tout[node] = tm_++; } void add_to_trie(int x, int y) { int cur = root; for (int i = BT - 1; i >= 0; --i) { int cb = (x >> i) & 1; ensure_child(cur, cb); int nxt = trie[cur].ch[cb]; trie[nxt].pass++; // child node pass count // store y in the parent's bucket for edge cb (like original code) // keep sorted by insertion insert_sorted_vec(trie[cur].tins[cb], y); cur = nxt; } } void del_from_trie(int x, int y) { // If you need deletions (original lazy used only cnt--), // we only decrement pass counts along path; we won't physically remove y from vectors int cur = root; for (int i = BT - 1; i >= 0; --i) { int cb = (x >> i) & 1; int nxt = trie[cur].ch[cb]; if (!nxt) return; // nothing to do trie[nxt].pass--; cur = nxt; } } int get_xor_max_in_range(int x, int L, int R) { int cur = root; int ans = 0; for (int i = BT - 1; i >= 0; --i) { if (!cur) break; int cb = (x >> i) & 1; int want = cb ^ 1; int kid = trie[cur].ch[want]; if (kid && trie[kid].pass > 0) { auto &vec = trie[cur].tins[want]; auto it = lower_bound(vec.begin(), vec.end(), L); if (it != vec.end() && *it <= R) { ans |= (1 << i); cur = kid; continue; } } // else go to same bit child cur = trie[cur].ch[cb]; } return ans; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); #if 0 // debug: turn off ios sync when not needed #endif trie.reserve(1<<20); // reserve some space so push_backs don't reallocate too often trie.clear(); root = new_node(); // root is 0 add_to_trie(0, 1); // initial st[1] = 0; int q; if (!(cin >> q)) return 0; V<pair<int,pii>> qr(q+1); // read all queries, build the tree of nodes (adj) int cur_n = 1; rep(i,1,q,1) { string s; int x,b; cin >> s >> x >> b; if (s[0] == 'A') { ++cur_n; st[cur_n] = st[x] ^ b; adj[x].pb(cur_n); qr[i] = {0, {cur_n, b}}; } else { qr[i] = {1, {x, b}}; } } // dfs once to compute tin/tout dfs(1); // Process queries in order: for 'A' do add (with tin known), for query do get rep(i,1,q,1) { if (qr[i].ff == 0) { int node = qr[i].ss.ff; add_to_trie(st[node], tin[node]); } else { int xnode = qr[i].ss.ff; int ynode = qr[i].ss.ss; cout << get_xor_max_in_range(st[xnode], tin[ynode], tout[ynode]) << '\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...