diff --git a/segment_tree/segment_trees_lazy.cpp.cpp b/segment_tree/segment_trees_lazy.cpp.cpp new file mode 100644 index 00000000..8d6be6b3 --- /dev/null +++ b/segment_tree/segment_trees_lazy.cpp.cpp @@ -0,0 +1,120 @@ +/** + * In this code we have a very large array called arr, and very large set of operations + * Operation #1: Increment the elements within range [i, j] with value val + * Operation #2: Get max element within range [i, j] + * Build tree: build_tree(1, 0, N-1) + * Update tree: update_tree(1, 0, N-1, i, j, value) + * Query tree: query_tree(1, 0, N-1, i, j) + * Actual space required by the tree = 2*2^ceil(log_2(n)) - 1 + */ + +#include +#include +using namespace std; + +#include +#include + +#define N 20 +#define MAX (1+(1<<6)) // Why? :D +#define inf 0x7fffffff + +int arr[N]; +int tree[MAX]; +int lazy[MAX]; + +/** + * Build and init tree + */ +void build_tree(int node, int a, int b) { + if(a > b) return; // Out of range + + if(a == b) { // Leaf node + tree[node] = arr[a]; // Init value + return; + } + + build_tree(node*2, a, (a+b)/2); // Init left child + build_tree(node*2+1, 1+(a+b)/2, b); // Init right child + + tree[node] = max(tree[node*2], tree[node*2+1]); // Init root value +} + +/** + * Increment elements within range [i, j] with value value + */ +void update_tree(int node, int a, int b, int i, int j, int value) { + + if(lazy[node] != 0) { // This node needs to be updated + tree[node] += lazy[node]; // Update it + + if(a != b) { + lazy[node*2] += lazy[node]; // Mark child as lazy + lazy[node*2+1] += lazy[node]; // Mark child as lazy + } + + lazy[node] = 0; // Reset it + } + + if(a > b || a > j || b < i) // Current segment is not within range [i, j] + return; + + if(a >= i && b <= j) { // Segment is fully within range + tree[node] += value; + + if(a != b) { // Not leaf node + lazy[node*2] += value; + lazy[node*2+1] += value; + } + + return; + } + + update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child + update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child + + tree[node] = max(tree[node*2], tree[node*2+1]); // Updating root with max value +} + +/** + * Query tree to get max element value within range [i, j] + */ +int query_tree(int node, int a, int b, int i, int j) { + + if(a > b || a > j || b < i) return -inf; // Out of range + + if(lazy[node] != 0) { // This node needs to be updated + tree[node] += lazy[node]; // Update it + + if(a != b) { + lazy[node*2] += lazy[node]; // Mark child as lazy + lazy[node*2+1] += lazy[node]; // Mark child as lazy + } + + lazy[node] = 0; // Reset it + } + + if(a >= i && b <= j) // Current segment is totally within range [i, j] + return tree[node]; + + int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child + int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child + + int res = max(q1, q2); // Return final result + + return res; +} + +int main() { + for(int i = 0; i < N; i++) arr[i] = 1; + + build_tree(1, 0, N-1); + + memset(lazy, 0, sizeof lazy); + + update_tree(1, 0, N-1, 0, 6, 5); // Increment range [0, 6] by 5. here 0, N-1 represent the current range. + update_tree(1, 0, N-1, 7, 10, 12); // Incremenet range [7, 10] by 12. here 0, N-1 represent the current range. + update_tree(1, 0, N-1, 10, N-1, 100); // Increment range [10, N-1] by 100. here 0, N-1 represent the current range. + + cout << query_tree(1, 0, N-1, 0, N-1) << endl; // Get max element in range [0, N-1] +} \ No newline at end of file