Last active
August 29, 2015 13:55
-
-
Save Jangwa/8691598 to your computer and use it in GitHub Desktop.
Lazy Propagation means that you only update what you actually need to, when you need to. For example, if we have a segment tree that covers the range 1-20. If we update segment [1,20], we update only the value of the root node of the tree and set a flag on it's children [1,10] and [11,20] to let them know that they need to be updated. Next, if w…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<algorithm> | |
using namespace std; | |
#include<string.h> | |
#include<math.h> | |
#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] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment