제출 #1252731

#제출 시각아이디문제언어결과실행 시간메모리
1252731mazen_ghanayemKlasika (COCI20_klasika)C++20
33 / 110
5090 ms10776 KiB
#include <iostream> #include <vector> #include <algorithm> #define nl "\n" // --- Persistent Binary Trie (Clean Template) --- // This is a clean, encapsulated C++ implementation based on the logic of the // accepted competitive programming solution. It uses a pre-allocated node pool // and integer indices instead of raw pointers to achieve high performance and // avoid runtime errors. class PersistentBinaryTrie { private: static const int BITS = 30; // For values up to 2^30 struct Node { int children[2]; int count; Node() : count(0) { children[0] = children[1] = 0; // Index 0 is the sentinel null node. } }; std::vector<Node> node_pool; std::vector<int> roots; int node_idx; int clone_node(int u) { node_pool[node_idx] = node_pool[u]; return node_idx++; } int insert_internal(int root_idx, int val) { int new_root = clone_node(root_idx); node_pool[new_root].count++; int curr_new = new_root; int curr_old = root_idx; for (int i = BITS - 1; i >= 0; --i) { int bit = (val >> i) & 1; int old_child_idx = node_pool[curr_old].children[bit]; int new_child_idx = clone_node(old_child_idx); node_pool[curr_new].children[bit] = new_child_idx; node_pool[new_child_idx].count++; curr_new = new_child_idx; curr_old = old_child_idx; } return new_root; } int query_max_xor(int l_root_idx, int r_root_idx, int x) { int y = 0; for (int i = BITS - 1; i >= 0; --i) { int bit = (x >> i) & 1; int required_bit = 1 - bit; int r_child_idx = node_pool[r_root_idx].children[required_bit]; int l_child_idx = node_pool[l_root_idx].children[required_bit]; if (node_pool[r_child_idx].count > node_pool[l_child_idx].count) { y |= (required_bit << i); r_root_idx = r_child_idx; l_root_idx = l_child_idx; } else { y |= (bit << i); r_root_idx = node_pool[r_root_idx].children[bit]; l_root_idx = node_pool[l_root_idx].children[bit]; } } return y; } public: PersistentBinaryTrie(int max_nodes) { node_pool.resize(max_nodes * (BITS + 2)); node_idx = 1; roots.reserve(max_nodes + 1); roots.push_back(0); } void add(int x) { roots.push_back(insert_internal(roots.back(), x)); } int get_max_xor(int l, int r, int x) { // Note: The PBT works on a 0-indexed array, but the problem uses 1-based ranges. // The calling context must handle this conversion. return query_max_xor(roots[l - 1], roots[r], x); } }; // --- Solver for the "Klasika" Problem --- class KlasikaSolver { private: struct Edge { int to; int weight; }; int node_count; std::vector<std::vector<Edge>> adj; std::vector<int> dist; // XOR sum from root 1 to node i // For mapping tree to 1D array std::vector<int> tin, tout, dfs_order; int timer; void dfs_flattener(int u, int p, int current_xor_dist) { tin[u] = ++timer; dfs_order[timer] = u; dist[u] = current_xor_dist; for (const auto& edge : adj[u]) { int v = edge.to; if (v != p) { dfs_flattener(v, u, current_xor_dist ^ edge.weight); } } tout[u] = timer; } public: KlasikaSolver(int max_q) { node_count = 1; adj.resize(max_q + 2); dist.resize(max_q + 2); tin.resize(max_q + 2); tout.resize(max_q + 2); dfs_order.resize(max_q + 2); dist[1] = 0; } void add_node(int parent, int weight) { node_count++; adj[parent].push_back({node_count, weight}); adj[node_count].push_back({parent, weight}); // Assuming undirected for dist calculation } int process_query(int a, int b) { // 1. Flatten the current tree structure with a DFS timer = 0; dfs_flattener(1, 0, 0); // 2. Build a temporary PBT on the DFS-ordered distances PersistentBinaryTrie pbt(node_count); for (int i = 1; i <= node_count; ++i) { int node_id = dfs_order[i]; pbt.add(dist[node_id]); } // 3. The subtree of `b` is now the range [tin[b], tout[b]] int l = tin[b]; int r = tout[b]; int val_a = dist[a]; // 4. Query the PBT for the best partner and return the max XOR value int best_partner = pbt.get_max_xor(l, r, val_a); return val_a ^ best_partner; } }; void solve() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); int q; std::cin >> q; KlasikaSolver solver(q); for (int i = 0; i < q; ++i) { std::string type; std::cin >> type; if (type == "Add") { int x, y; std::cin >> x >> y; solver.add_node(x, y); } else { // Query int a, b; std::cin >> a >> b; std::cout << solver.process_query(a, b) << nl; } } } int main() { solve(); 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...