From bba9ae8107fa88aca3c7b3f3af638f6f0962d832 Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Thu, 1 Feb 2018 18:47:15 -0200
Subject: [PATCH] Add lazy_segment_tree

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 structure/lazy_segment_tree.cpp | 89 +++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 structure/lazy_segment_tree.cpp

diff --git a/structure/lazy_segment_tree.cpp b/structure/lazy_segment_tree.cpp
new file mode 100644
index 0000000..61ecf39
--- /dev/null
+++ b/structure/lazy_segment_tree.cpp
@@ -0,0 +1,89 @@
+/**
+ * Lazy Segment Tree
+ *
+ * Complexity (Time):
+ *   build_tree  -> O(n log n)
+ *   update_tree -> O(log n)
+ *   query_tree  -> O(log n)
+ * Complexity (Space): O(n)
+ */
+
+int N, tree[2 * MAX], lazy[2 * MAX], v[MAX];
+
+// Build tree with elements from v
+void build_tree(int node = 1, int a = 0, int b = N) {
+  if (a > b)
+    return;
+
+  if (a == b) {
+    tree[node] = v[a];
+    return;
+  }
+
+  build_tree(node * 2, a, (a + b) / 2);
+  build_tree(node * 2 + 1, 1 + (a + b) / 2, b);
+
+  tree[node] = tree[node * 2] + tree[node * 2 + 1];
+}
+
+int modification(int a, int b, int val) {
+  return ((b - a) + 1) * val;
+}
+
+// Update segment [i,j] by adding value val
+void update_tree(int i, int j, int val, int node = 1, int a = 0, int b = N) {
+  if (lazy[node] != 0) {
+    tree[node] += modification(a, b, lazy[node]);
+
+    if (a != b) {
+      lazy[node * 2] += lazy[node];
+      lazy[node * 2 + 1] += lazy[node];
+    }
+
+    lazy[node] = 0;
+  }
+
+  if (a > b || a > j || b < i)
+    return;
+
+  if (a >= i && b <= j) {
+    tree[node] += modification(a, b, val);
+
+    if (a != b) {
+      lazy[node * 2] += val;
+      lazy[node * 2 + 1] += val;
+    }
+
+    return;
+  }
+
+  update_tree(i, j, node * 2, a, (a + b) / 2);
+  update_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b);
+
+  tree[node] = tree[node * 2] + tree[node * 2 + 1];
+}
+
+// Return sum from i to j
+int query_tree(int i, int j, int node = 1, int a = 0, int b = N) {
+  if (a > b || a > j || b < i)
+    return 0;
+
+  if (lazy[node] != 0) {
+    tree[node] += modification(a, b, lazy[node]);
+
+    if (a != b) {
+      lazy[node * 2] += lazy[node];
+      lazy[node * 2 + 1] += lazy[node];
+    }
+
+    lazy[node] = 0;
+  }
+
+  if (a >= i && b <= j)
+    return tree[node];
+
+  int q1 = query_tree(i, j, node * 2, a, (a + b) / 2);
+  int q2 = query_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b);
+
+  return q1 + q2;
+}
-- 
GitLab