From f7366924f269ad920144c944717a56b4a170c8bd Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Fri, 15 Feb 2019 16:12:12 -0200
Subject: [PATCH] Fix lazy seg tree

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 algorithms/structure/lazy_segment_tree.cpp |  48 +++----
 contests/Cadernaveis/URI1477.cpp           | 148 +++++++++++++++++++++
 2 files changed, 172 insertions(+), 24 deletions(-)
 create mode 100644 contests/Cadernaveis/URI1477.cpp

diff --git a/algorithms/structure/lazy_segment_tree.cpp b/algorithms/structure/lazy_segment_tree.cpp
index 9f7552a..1fac1b0 100644
--- a/algorithms/structure/lazy_segment_tree.cpp
+++ b/algorithms/structure/lazy_segment_tree.cpp
@@ -10,9 +10,9 @@
 
 int N, tree[4 * MAX], lazy[4 * MAX], v[MAX];
 
-// Build tree with elements from v
-void build_tree(int node = 1, int a = 0, int b = N) {
-  if (a > b)
+// Builds tree with elements from v
+void build(int node = 1, int a = 0, int b = n) {
+  if (a > b) 
     return;
 
   if (a == b) {
@@ -20,14 +20,16 @@ void build_tree(int node = 1, int a = 0, int b = N) {
     return;
   }
 
-  build_tree(node * 2, a, (a + b) / 2);
-  build_tree(node * 2 + 1, 1 + (a + b) / 2, b);
+  build(node * 2, a, (a + b) / 2);
+  build(node * 2 + 1, (a + b) / 2 + 1, b);
   tree[node] = tree[node * 2] + tree[node * 2 + 1];
 }
 
 
-void push(int node, int val) {
-  tree[node] += value;
+// Propagates value to tree and through lazy tree
+void push(int node, int a, int b, int val) {
+  tree[node] += val;
+  // tree[node] += (b - a + 1) * val; (for Range Sum Query)
 
   if (a != b) {
     lazy[node * 2] += val;
@@ -38,39 +40,37 @@ void push(int node, int 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) {
+// Updates segment [i,j] by adding value val
+void update(int i, int j, int val, int node = 1, int a = 0, int b = n) {
   if (lazy[node] != 0)
-    push(node, lazy[node]);
+    push(node, a, b, lazy[node]);
 
-
-  if (a > b || a > j || b < i)
+  if (a > b or a > j or b < i) 
     return;
 
-  if (a >= i && b <= j) {
-    push(node, val);
+  if (a >= i and b <= j) {
+    push(node, a, b, val);
     return;
   }
 
-  update_tree(i, j, node * 2, a, (a + b) / 2);
-  update_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b);
+  update(i, j, val, node * 2, a, (a + b) / 2);
+  update(i, j, val, node * 2 + 1, (a + b) / 2 + 1, b);
   tree[node] = tree[node * 2] + tree[node * 2 + 1];
 }
 
 
-// Return sum of [i,j]
-int query_tree(int i, int j, int node = 1, int a = 0, int b = N) {
+// Returns sum of [i,j]
+int query(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) {
-    push(node, val); 
-  }
+  if (lazy[node])
+    push(node, a, b, lazy[node]);
 
-  if (a >= i && b <= j)
+  if (a >= i and 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);
+  int q1 = query(i, j, node * 2, a, (a + b) / 2);
+  int q2 = query(i, j, node * 2 + 1, (a + b) / 2 + 1, b);
   return q1 + q2;
 }
diff --git a/contests/Cadernaveis/URI1477.cpp b/contests/Cadernaveis/URI1477.cpp
new file mode 100644
index 0000000..3790a06
--- /dev/null
+++ b/contests/Cadernaveis/URI1477.cpp
@@ -0,0 +1,148 @@
+#include <bits/stdc++.h>
+
+#define MAX 101010
+#define EPS 1e-6
+#define MOD 1000000007
+#define inf 0x3f3f3f3f
+#define llinf 0x3f3f3f3f3f3f3f3f
+
+#define fi first
+#define se second
+#define sz size()
+#define pb push_back
+#define ende '\n'
+
+#define all(x) (x).begin(), (x).end()
+#define rall(x) (x).rbegin(), (x).rend()
+#define mset(x, y) memset(&x, (y), sizeof(x))
+
+using namespace std; 
+
+typedef long long ll;
+typedef pair<int,int> ii;
+
+typedef struct elem {
+  int h, e, r;
+
+  elem() : h(0), e(0), r(0) {}
+  elem(int h, int e, int r) : h(h), e(e), r(r) {}
+
+  elem operator+(const elem &x) {
+    return elem(h + x.h, e + x.e, r + x.r);
+  }
+
+  void change(int n) {
+    int a = h, b = e, c = r;
+    if (n % 3 == 1) {
+      e = a;
+      r = b;
+      h = c;
+    } else if (n % 3 == 2) {
+      e = c;
+      r = a;
+      h = b;
+    }
+  }
+} elem;
+
+
+int n;
+elem v[MAX];
+elem tree[MAX * 4];
+int lazy[MAX * 4];
+
+void build(int node = 1, int a = 0, int b = n) {
+  if (a > b) return;
+
+  if (a == b) {
+    tree[node] = v[a];
+    return;
+  }
+
+  build(node * 2, a, (a + b) / 2);
+  build(node * 2 + 1, (a + b) / 2 + 1, b);
+  tree[node] = tree[node * 2] + tree[node * 2 + 1];
+}
+
+
+void push(int node, int a, int b, int val) {
+  tree[node].change(val);
+
+  if (a != b) {
+    lazy[node * 2] += val;
+    lazy[node * 2 + 1] += val;
+  }
+
+  lazy[node] = 0;
+}
+
+
+void update(int i, int j, int node = 1, int a = 0, int b = n) {
+  if (lazy[node] != 0)
+    push(node, a, b, lazy[node]); 
+
+  if (a > b or a > j or b < i) 
+    return;
+
+  if (a >= i and b <= j) {
+    push(node, a, b, 1);
+    return; 
+  }
+
+  update(i, j, node * 2, a, (a + b) / 2);
+  update(i, j, node * 2 + 1, (a + b) / 2 + 1, b);
+  tree[node] = tree[node * 2] + tree[node * 2 + 1];
+}
+
+
+elem query(int i, int j, int node = 1, int a = 0, int b = n) {
+  if (a > b || a > j || b < i)
+    return elem();
+
+  if (lazy[node])
+    push(node, a, b, lazy[node]);
+
+  if (a >= i and b <= j)
+    return tree[node];
+
+  elem q1 = query(i, j, node * 2, a, (a + b) / 2);
+  elem q2 = query(i, j, node * 2 + 1, (a + b) / 2 + 1, b);
+  return q1 + q2;
+}
+
+
+int main() {
+  ios::sync_with_stdio(0);
+  cin.tie(0);
+
+  int m; 
+  while (cin >> n >> m) {
+    for (int i = 0; i < MAX * 4; ++i) {
+      tree[i] = elem();
+      lazy[i] = 0;
+    }
+
+    for (int i = 0; i < n; ++i) {
+      v[i].h = 1;
+      v[i].e = v[i].r = 0;
+    }
+
+    build();
+
+    for (int i = 0; i < m; ++i) {
+      char op;
+      int a, b; cin >> op >> a >> b;
+
+      if (op == 'C') {
+        elem x = query(a - 1, b - 1);
+        cout << x.h << " " << x.e << " " << x.r << ende;
+      } else {
+        update(a - 1, b - 1);
+      }
+    }
+
+    cout << ende;
+  }
+
+  return 0;
+}
-- 
GitLab