Submission #1162245

#TimeUsernameProblemLanguageResultExecution timeMemory
1162245with_wageehMonkey and Apple-trees (IZhO12_apple)C++20
100 / 100
244 ms69164 KiB
#include <bits/stdc++.h> using namespace std; // SparseSegtree is designed for very large ranges (for example up to 1e9) // but only creates nodes for segments that are updated or queried. // It supports range "set" updates (assigning a given value to every element in a range) // and range sum queries. class SparseSegtree { private: // Each node stores: // - freq: the aggregate value (here, the sum of the segment) // - lazy: a lazy propagation marker (nonzero means that the node’s segment // should be updated to that value) // - left, right: indices in the tree vector for the left and right children. struct Node { int freq = 0; // sum of the segment int lazy = 0; // lazy marker for range-set updates; 0 means no pending update int left = -1; // index of left child in the tree vector (-1 if not created) int right = -1; // index of right child (-1 if not created) }; vector<Node> tree; // the collection of nodes (dynamically allocated as needed) const int n; // size of the overall range [0, n-1] int timer = 0; // used to assign indices for new nodes // Combine two segment values. // For a sum query, simply add the two values. inline int comb(int a, int b) { return a + b; } // Apply a range-set update to the current node. // 'cur' is the current node index. // 'len' is the length of the segment represented by this node. // 'val' is the value we want to assign over the entire segment. inline void apply(int cur, int len, int val) { // Set the lazy marker (indicating that the whole segment is updated to 'val') tree[cur].lazy = val; // Update the aggregate value (frequency) of this node. tree[cur].freq = len * val; } // Propagate the lazy update from the current node down to its children. // 'l' and 'r' represent the current segment boundaries. inline void push_down(int cur, int l, int r) { // Create left child if it doesn't exist if (tree[cur].left == -1) { tree[cur].left = ++timer; tree.push_back(Node()); } // Create right child if it doesn't exist if (tree[cur].right == -1) { tree[cur].right = ++timer; tree.push_back(Node()); } int m = (l + r) / 2; // mid-point of the segment // If there is a pending lazy update on the current node, push it to both children. if (tree[cur].lazy != 0) { apply(tree[cur].left, m - l + 1, tree[cur].lazy); apply(tree[cur].right, r - m, tree[cur].lazy); // Clear the lazy marker after propagation. tree[cur].lazy = 0; } } // Internal function to perform a range-set update. // It sets every element in the interval [ql, qr] to 'val'. // cur: current node index; [l, r] is the segment for this node. void range_set(int cur, int l, int r, int ql, int qr, int val) { // No overlap: simply return. if (qr < l || ql > r) return; // Total overlap: directly apply the update. if (ql <= l && r <= qr) { apply(cur, r - l + 1, val); } else { // Partial overlap: first push down any pending lazy updates. push_down(cur, l, r); int m = (l + r) / 2; // Recurse to left child. range_set(tree[cur].left, l, m, ql, qr, val); // Recurse to right child. range_set(tree[cur].right, m + 1, r, ql, qr, val); // Combine results from children. tree[cur].freq = comb(tree[tree[cur].left].freq, tree[tree[cur].right].freq); } } // Internal function to compute the range sum over [ql, qr]. // cur: current node index; [l, r] is the segment for this node. int range_sum(int cur, int l, int r, int ql, int qr) { // No overlap. if (qr < l || ql > r) return 0; // Total overlap. if (ql <= l && r <= qr) return tree[cur].freq; // Partial overlap: push down pending updates and combine query results. push_down(cur, l, r); int m = (l + r) / 2; return comb(range_sum(tree[cur].left, l, m, ql, qr), range_sum(tree[cur].right, m + 1, r, ql, qr)); } public: // Constructor: // 'n' is the overall size of the range. // 'q' (optional) is the expected number of queries, used to reserve space. SparseSegtree(int n, int q = 0) : n(n) { // Reserve extra space in the vector if a query count is given. if (q > 0) tree.reserve(2 * q * __lg(n)); // Create the root node which covers the whole range [0, n-1]. tree.push_back(Node()); } // Public interface for range_set update: // Sets all elements in the interval [ql, qr] to 'val'. void range_set(int ql, int qr, int val) { range_set(0, 0, n - 1, ql, qr, val); } // Public interface for range_sum query: // Returns the sum of values in the interval [ql, qr]. int range_sum(int ql, int qr) { return range_sum(0, 0, n - 1, ql, qr); } }; ////////////////////////// /// Main Program Demo /// ////////////////////////// int main() { int query_num; cin >> query_num; // In this example, we assume the overall range is 1e9 (rails numbered 0..1e9) const int RANGE_SIZE = 1e9; // Create the sparse segment tree. // We add 1 to RANGE_SIZE to cover [0, RANGE_SIZE] and pass the query count to reserve space. SparseSegtree st(RANGE_SIZE + 1, query_num); // 'c' is used to adjust query indices based on previous query results (a common technique in interactive problems). int c = 0; for (int i = 0; i < query_num; i++) { int type, x, y; cin >> type >> x >> y; // Query: when type == 1, perform a range sum query. if (type == 1) { // Adjust the query interval using c. c = st.range_sum(x + c, y + c); cout << c << '\n'; } // Update: when type == 2, perform a range-set update. // For the red-ripening event, the update value is 1. else if (type == 2) { st.range_set(x + c, y + c, 1); } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...