diff --git a/caderno/caderno.tex b/caderno/caderno.tex
index fea76c5b3f13263d042efe55530f33f79946bb38..5b5929e341b70df9006e3abe5a6355cae8cb0952 100644
--- a/caderno/caderno.tex
+++ b/caderno/caderno.tex
@@ -129,10 +129,10 @@ Estimativa computacional: $10^8$ operações em três segundos.
     $\leq [18..22]$ & $\bigO(2^n n)$ & ex. PD com técnica de máscara de bits \\
     $\leq 100$ & $\bigO(n^4)$ & ex. PD com 3 dimensões + laço $O(n)$, $_{n}C_{k=4}$ \\
     $\leq 400$ & $\bigO(n^3)$ & ex. Floyd-Warshall \\
-    $\leq 2\cdot 10^3$ & $\bigO(n^2 \lg n)$ & ex. 2 laços aninhados + EdD Árvore \\
-    $\leq 10^6$ & $\bigO(n^2)$ & ex. Bubble/Seleçtion/Insertion Sort \\
-    $\leq 10^9$ & $\bigO(n \lg n)$ & ex. Merge Sort, construir Árvore de Segmento \\
-    $\leq 10^{11}$ & $\bigO(n)$, $\bigO(\lg n)$, $\bigO(1)$ & Maioria dos problemas tem $n \leq 10^9$ (gargalo de E/S) \\
+    $\leq 2\cdot 10^3$ & $\bigO(n^2 \lg n)$ & ex. 2 laços aninhados + consulta em árvore \\
+    $\leq 10^4$ & $\bigO(n^2)$ & ex. Bubble/Selection/Insertion Sort \\
+    $\leq 10^6$ & $\bigO(n \lg n)$ & ex. Merge Sort, construir árvore de segmento \\
+    $\leq 10^8$ & $\bigO(n)$, $\bigO(\lg n)$, $\bigO(1)$ & Maioria dos problemas tem $n \leq 10^9$ (gargalo de E/S) \\
   \end{tabular}
 \end{center}
 
diff --git a/fontes/binary-lifting.cpp b/fontes/binary-lifting.cpp
index cd50879224a3cee633b834eea76287c44be8d3a7..3dfd8386b4936c787bfd592b177a0d4b08e44088 100644
--- a/fontes/binary-lifting.cpp
+++ b/fontes/binary-lifting.cpp
@@ -1,45 +1,50 @@
-vi heights (N, 0);
-vvi weights (N, vi(D+1, 0));
-vvi parents (N, vi(D+1, -1));
-
-void bl_euler_tour (int u, int parent, int w) {
-  parents[u][0] = parent;
-  weights[u][0] = w;
-
-  if (parent != -1)
-    heights[u] = heights[parent] + 1;
-
-  for (int d = 0, mid; d <= D
-      && (mid = parents[u][d]) != -1; d++) {
-    parents[u][d+1] = parents[mid][d];
-    mmax(weights[u][d+1],
-        weights[u][d], weights[mid][d]);
+const int D = log2(N);
+vector<int> depth (N, 0);
+vector<int> wsum (N);
+vector<vector<int>> weight (N, vector<int>(D+1));
+vector<vector<int>> up (N, vector<int>(D+1));
+
+// call (u, u, 0), set depth[u] = 0
+void bl_euler_tour (int u, int p, int w) {
+  up[u][0] = p;
+  weight[u][0] = w;
+  wsum[u] = wsum[p] + w;
+  depth[u] = depth[p] + 1;
+  for (int d = 0; d < D; d++) {
+    int a = up[u][d];
+    up[u][d+1] = up[a][d];
+    weight[u][d+1] = max(weight[u][d], weight[a][d]);
   }
-
-  for (auto e : graph[u]) if (e.vv != parent)
+  for (auto e : graph[u]) if (e.vv != p)
     bl_euler_tour(e.vv, u, e.ww);
 }
 
-int bl_query (int a, int b) {
-  int result = 0;
-  if (heights[b] > heights[a]) { swap(a, b); }
+// also bl_lca, just return lca and exclude res
+int bl_query_path (int a, int b) {
+  // if b is deeper than a, swap
+  if (depth[b] > depth[a]) { swap(a, b); }
 
-  for (int d = D; d >= 0; d--)
-    if (parents[a][d] != -1
-        && heights[parents[a][d]] >= heights[b]) {
-      mmax(result, weights[a][d]);
-      a = parents[a][d];
-    }
+  int res = 0;
 
-  if (a == b) { return result; }
+  int diff = depth[a] - depth[b];
+  for (int d = D; d >= 0; d--) if (diff & (1 << d)) {
+    res = max(res, weight[a][d]);
+    a = up[a][d];
+  }
+
+  if (a == b) { /* lca == a */ return res; }
 
   for (int d = D; d >= 0; d--)
-    if (parents[a][d] != parents[b][d]) {
-      mmax(result, weights[a][d], weights[b][d]);
-      a = parents[a][d]; b = parents[b][d];
+    if (up[a][d] != up[b][d]) {
+      res = max({ res, weight[a][d], weight[b][d] });
+      a = up[a][d], b = up[b][d];
     }
 
-  if (a == b) { return result; }
+  // lca == up[a][0]
+  return max({ res, weight[a][0], weight[b][0] });
+}
 
-  return max({result, weights[a][0], weights[b][0]});
+int bl_query_sum (int a, int b) {
+  int lca = bl_lca(a, b);
+  return (wsum[a] - wsum[lca]) + (wsum[b] - wsum[lca]);
 }
diff --git a/fontes/convex-hull.cpp b/fontes/convex-hull.cpp
index 5b5bd585c4cb909ba3d52bf725d261b65dd4f9a7..a085409662427f99c1a9fb73ef922a5b82997ea5 100644
--- a/fontes/convex-hull.cpp
+++ b/fontes/convex-hull.cpp
@@ -1,26 +1,26 @@
-bool ch_order (dd o, dd a, dd b) {
-  return (a.xx - o.xx) * (b.yy - o.yy)
-    - (a.yy - o.yy) * (b.xx - o.xx) > 0;
+int sgn (double v) { return (v > 0) - (v < 0); }
+// -1 (cw), 0 (colinear), +1 (ccw)
+int seg_ornt (pt a, pt b, pt c) {
+  return sgn((conj(b - a) * (c - a)).py);
 }
 
-vdd convex_hull /* O(n lg n) */ (vdd ps) {
-  int k = 0, i, t;
-  vdd result (sz(ps) * 2);
+vpt convex_hull /* O(n lg n) */ (vpt& ps) {
+  int k = 0, n = ps.size();
+  vpt result (n * 2);
 
-  sort(all(ps), [](dd a, dd b) {
-    return (a.xx == b.xx)
-          ? (a.yy < b.yy) : (a.xx < b.xx);
+  sort(all(ps), [](pt a, pt b) {
+    return mp(a.px, a.py) < mp(b.px, b.py);
   });
 
-  for (i = 0; i < sz(ps); i++) {
-    while (k >= 2 && !ch_order( /* lower hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = 0; i < n; i++) {
+    while (k >= 2 && seg_ornt( /* lower hull */
+        result[k-2], result[k-1], ps[i]) <= 0) k--;
     result[k++] = ps[i];
   }
 
-  for (i = sz(ps) - 2, t = k + 1; i >= 0; i--) {
-    while (k >= t && !ch_order( /* upper hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = n - 2, t = k + 1; i >= 0; i--) {
+    while (k >= t && seg_ornt( /* upper hull */
+        result[k-2], result[k-1], ps[i]) <= 0) k--;
     result[k++] = ps[i];
   }
 
diff --git a/fontes/crivo.cpp b/fontes/crivo.cpp
deleted file mode 100644
index df945bc54bdf42b3480510f8bb1bc0e5660eee31..0000000000000000000000000000000000000000
--- a/fontes/crivo.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-void gen_primes() {
-  int i,j;
-  for(i=0;i<MAX;i++) primes[i] = 1;
-  for(i=2;i<=(int)sqrt(MAX);i++)
-    if (primes[i])
-      for(j=i;j*i<MAX;j++) primes[i*j] = 0;
-}
diff --git a/fontes/extended-gcd.cpp b/fontes/extended-gcd.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..33c53259e7ef6afe6a98b9af34aa1647d0c65525
--- /dev/null
+++ b/fontes/extended-gcd.cpp
@@ -0,0 +1,12 @@
+// ax + by = gcd(a, b)
+// ax = gcd(a, b) (mod b)
+// (gcd(a, b) = 1) => (ax = 1 (mod b))
+//
+// Time: O(lg min(a, b)
+// Space: O(1)
+struct gans { ll x, y, d; };
+gans ext_gcd(ll a, ll b) {
+    if (a == 0) return { 0, 1, b };
+    gans e = ext_gcd(b % a, a);
+    return { e.y - (b/a)*e.x, e.x, e.d };
+}
diff --git a/fontes/fast-pow.cpp b/fontes/fast-pow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..537f1481fadbe720902d3d4e05e96259af57e3e6
--- /dev/null
+++ b/fontes/fast-pow.cpp
@@ -0,0 +1,8 @@
+ll fast_pow (ll& res, ll a, ll e) {
+  if (e == 0) { return res = 1; }
+  if (e == 1) { return res = a; }
+  /* ll res = */ fast_pow(res, a, e/2);
+  res = res * res;
+  if (e % 2) res = res * a;
+  return res;
+}
diff --git a/fontes/fenwick-2d-tree.cpp b/fontes/fenwick-2d-tree.cpp
index 0f108e40a85985bfad54e0137b53a0516538691b..a2f401fd251835f35569000d109ab73bcc2afea5 100644
--- a/fontes/fenwick-2d-tree.cpp
+++ b/fontes/fenwick-2d-tree.cpp
@@ -1,5 +1,4 @@
-int ftN = 103, ftM = 103; // O(n^2)
-vvi ftree(ftN, vector<int>(ftM, 0)); // 1-indexed
+vvi ftree(ftN, vi(ftM, 0)); // 1-indexed
 
 void ft_add /* O(lg^2 n) */ (int x,int y,int d) {
   for (; x < ftN; x += x & -x)
diff --git a/fontes/fenwick-range-tree.cpp b/fontes/fenwick-range-tree.cpp
index bf9812568dbf0f9c2594edc4093d9597a1e07669..b9a0c753535dc161a91cddcd1567b90cb96ec079 100644
--- a/fontes/fenwick-range-tree.cpp
+++ b/fontes/fenwick-range-tree.cpp
@@ -2,7 +2,7 @@ int ftN = 4*N; // O(n)
 vi tree_a = vi(ftN, 0); // 1-indexed
 vi tree_b = vi(ftN, 0); // 1-indexed
 
-// copy add and query, add &ftree param
+// copy add and query
 
 int prefix_sum (int i) {
   return query(tree_a, i) * i - query(tree_b, i);
diff --git a/fontes/fenwick-tree.cpp b/fontes/fenwick-tree.cpp
index 4ef2b498e3a8bf9f4478e37513e1ade0e4ee7fc2..7e90604a45d660dfd02df655046b14b6a09ee9fa 100644
--- a/fontes/fenwick-tree.cpp
+++ b/fontes/fenwick-tree.cpp
@@ -1,8 +1,8 @@
-int ftN = 4*N; // O(n)
-vi ftree(ftN, 0); // 1-indexed
+int ft_n = N; // O(n)
+vi ftree(ft_n, 0); // 1-indexed
 
 void add /* O(lg n) */ (int i, int d) {
-  for (; i < ftN; i += i & -i)
+  for (; i < ft_n; i += i & -i)
     ftree[i] += d;
 }
 
@@ -14,7 +14,7 @@ int query /* O(lg n) */ (int i) {
 }
 
 // 1: add + range_sum, query is query_upto
-int range_sum /* O(lg n) */ (int i, int j) {
+int range_query /* O(lg n) */ (int i, int j) {
   return query(j) - query(i - 1);
 }
 
diff --git a/fontes/geometry.cpp b/fontes/geometry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..187ec50dbb5f0189e3689f39ca7bfa68d7f9b843
--- /dev/null
+++ b/fontes/geometry.cpp
@@ -0,0 +1,62 @@
+#define aa first
+#define bb second
+#define px real()
+#define py imag()
+
+typedef complex<double> point;
+typedef pair<pt, pt> seg;
+
+double dot(pt a, pt b) { return (conj(a) * b).px; }
+double cross(pt a, pt b) { return (conj(a) * b).py; }
+pt vec(pt a, pt b) { return b - a; }
+pt vec(seg s) { return s.bb - s.aa; }
+
+// faster
+bool on_segment(seg s, point p) {
+  return cross(s.aa - p, s.bb - p) == 0 && dot(s.aa - p, s.bb - p) <= 0;
+}
+
+// slower
+bool on_segment(seg s, point p) {
+  return (
+    p.px <= max(s.aa.px, s.bb.px) &&
+    p.px >= min(s.aa.px, s.bb.px) &&
+    p.py <= max(s.aa.py, s.bb.py) &&
+    p.py >= min(s.aa.py, s.bb.py));
+}
+
+int sgn (int v) {
+  return (v > 0) - (v < 0);
+}
+
+int ord_ornt (seg s, point c) {
+  return sgn(cross(vec(s), vec(s.bb, c)));
+}
+
+bool intersect_seg(seg s, seg t) {
+  int o1 = ord_ornt(s, t.aa), o2 = ord_ornt(s, t.bb);
+  int o3 = ord_ornt(t, s.aa), o4 = ord_ornt(t, s.bb);
+
+  return (
+    (o1 != o2 && o3 != o4) ||
+    (o1 == 0 && on_segment(s, t.aa)) ||
+    (o2 == 0 && on_segment(s, t.bb)) ||
+    (o3 == 0 && on_segment(t, s.aa)) ||
+    (o4 == 0 && on_segment(t, s.bb)));
+}
+
+double distance_seg_point(point p, seg s) {
+    if (s.aa == s.bb) { return abs(p - s.aa); }
+    double nsq = norm(vec(s));
+    double l = min(nsq, max(0.0, dot(vec(s), vec(s.aa, p))));
+    return abs(nsq*vec(s.aa, p) - l*vec(s)) / nsq;
+}
+
+double distance_seg_seg(seg s, seg t) {
+    if (intersect_seg(s, t)) { return 0; }
+    double v1 = distance_seg_point(s.aa, t);
+    double v2 = distance_seg_point(s.bb, t);
+    double v3 = distance_seg_point(t.aa, s);
+    double v4 = distance_seg_point(t.bb, s);
+    return min({ v1, v2, v3, v4 });
+}
diff --git a/fontes/gnu.cpp b/fontes/gnu.cpp
index e7e6a94aad7918da6882b82921dfd9aa4236b6f6..0052c43e2d8f1a00c92909b9acc880dcbce3a60e 100644
--- a/fontes/gnu.cpp
+++ b/fontes/gnu.cpp
@@ -1,5 +1,7 @@
-__builtin_ffs // 1 + position of 1 MSB
+// Add ll at the end for long long
+__builtin_ffs // 1 + position of 1 LSB
 __builtin_ctz // count trailing zeros
 __builtin_clz // count zeros in front
 __builtin_popcount // count how many bits are set
-__builtin_parity(int) // same as above mod 2
+// Position of 1 MSB
+i != 0 ? sizeof(int)*8 - __builtin_clz(i) : 0
diff --git a/fontes/iterative-lazy-segment-tree.cpp b/fontes/iterative-lazy-segment-tree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ea9d0f0a883a070bbc7de1b97ba11537c71b5ba
--- /dev/null
+++ b/fontes/iterative-lazy-segment-tree.cpp
@@ -0,0 +1,69 @@
+#include <stdbool.h>
+#define N 1<<17
+#define LEFT 2*i
+#define RIGH 2*i+1
+#define M (ta+tb)/2
+
+struct segtree {
+  int n, h;
+  struct node t[2 * N];
+  struct node_update d[N];
+  struct node (*merge)(struct node*, struct node*);
+  struct node_update (*merge_upd)(struct node_update*, struct node_update*);
+  struct node (*apply_upd)(struct node*, struct node_update*);
+  bool (*upd_done)(struct node_update*);
+  void (*upd_clear)(struct node_update*);
+
+  void init() {
+    irof(i, 0, n) t[i] = tr->merge(&t[LEFT], &t[RIGH]);
+    fori(i, 0, N) upd_clear(&d[i]);
+  }
+
+  void apply (int p, struct node_update* upd) {
+    t[p] = apply_upd(t[p], upd);
+    if (p < n) d[p] = merge_upd(&d[p], upd);
+  }
+
+  void build (int i) {
+    while (i > 1) {
+      i /= 2;
+      t[i] = OP(&t[LEFT], &tr->t[RIGH]);
+      t[i] = apply_upd(&t[p], &d[p]);
+    }
+  }
+
+  void push (int p) {
+    irof(s, 0, h+1) {
+      int i = p >> s;
+      if (!upd_done(&d[i])) {
+        apply(tr, LEFT, &d[i]);
+        apply(tr, RIGH, &d[i]);
+        upd_clear(&d[i]);
+      }
+    }
+  }
+
+  void set_range (int l, int r, struct node_update* upd) {
+    l += n, r += n;
+    push(l);
+    push(r - 1);
+    int l0 = l, r0 = r;
+    for (; l < r; l /= 2, r /= 2) {
+      if (l & 1) apply(tr, l++, upd);
+      if (r & 1) apply(tr, --r, upd);
+    }
+    build(l0);
+    build(r0 - 1);
+  }
+
+  T query_range (int l, int r) {
+    l += n, r += n;
+    push(l); push(r - 1);
+    T r1 = NEUTRAL, r2 = NEUTRAL;
+    for (; l < r; l /= 2, r /= 2) {
+      if (l & 1) r1 = OP(r1, t[l++]);
+      if (r & 1) r2 = OP(t[--r], r2);
+    }
+    return OP(r1, r2);
+  }
+};
diff --git a/fontes/kmp.cpp b/fontes/kmp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5b51dfa239177b5c14f6d0665172e22999491642
--- /dev/null
+++ b/fontes/kmp.cpp
@@ -0,0 +1,26 @@
+vector<int> kmp_pre(string haystack, string needle) {
+    vector<int> backtrack(haystack.size());
+    backtrack[0] = -1;
+
+    int i = 0, j = -1;
+    while (i < needle.size()) {
+        while (j >= 0 && needle[i] != needle[j]) j = backtrack[j];
+        i++; j++;
+        backtrack[i] = j;
+    }
+
+    return backtrack;
+}
+
+void kmp_search(string haystack, string needle) {
+    vector<int> backtrack = kmp_pre(haystack, needle);
+
+    int i = 0, j = 0;
+    while (i < haystack.size()) {
+        while (j >= 0 && haystack[i] != needle[j]) j = backtrack[j];
+        i++; j++;
+        if (j == needle.size()) {
+          // match at (i - j)
+        }
+    }
+}
diff --git a/fontes/kosaraju.cpp b/fontes/kosaraju.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a618c7a7adf41a58650e4dc6bf4cda310e800bec
--- /dev/null
+++ b/fontes/kosaraju.cpp
@@ -0,0 +1,41 @@
+int timestamp = 0;
+vector<bool> visited(n);
+vector<vector<int>> G (n);
+vector<vector<int>> G_t (n);
+vector<int> rep (1e5 + 1);
+stack<int> S;
+
+void fill_stack (int u) {
+  visited[u] = timestamp;
+  for (int v : G[u]) if (visited[v] != timestamp) {
+    fill_stack(v);
+  }
+  S.push(u);
+}
+
+void mark_component (int u, int my_rep) {
+  visited[u] = timestamp;
+  rep[u] = my_rep;
+  for (int v : G_t[u]) if (visited[v] != timestamp) {
+    mark_component(v, my_rep);
+  }
+}
+
+vector<int> kosaraju (int n) {
+  timestamp++;
+  for (int u = 0; u < n; u++) if (visited[u] != timestamp) {
+    fill_stack(u);
+  }
+
+  timestamp++;
+  vector<int> topo_components;
+  while (!S.empty()) {
+    int u = S.top(); S.pop();
+    if (visited[u] != timestamp) {
+      mark_component(u);
+      topo_components.push_back(u);
+    }
+  }
+
+  return topo_components;
+}
diff --git a/fontes/kruskal.cpp b/fontes/kruskal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35299cff36b3eb9145d08d52206e4aeb9b772392
--- /dev/null
+++ b/fontes/kruskal.cpp
@@ -0,0 +1,40 @@
+typedef pair<int, pair<int, int>> edge;
+// edge -> e.cc, (e.uu.xx, e.uu.yy)
+
+vector<int> rep (n);
+vector<int> rnk (n);
+vector<int> siz (n, 1);
+vector<edge> edges;
+
+int ds_find(int u) {
+  if (rep[u] != u) { rep[u] = ds_find(rep[u]); }
+  return rep[u];
+}
+
+void ds_union(int u, int v) {
+  u = ds_find(u); v = ds_find(v);
+
+  assert(u != v);
+  if (!(rnk[u] > rnk[v])) { swap(u, v); }
+  if (rnk[u] == rnk[v]) { rnk[u]++; }
+  rep[v] = u;
+  siz[u] += siz[v];
+}
+
+int kruskal(int n) {
+  sort(edges.begin(), edges.end());
+  for (int u = 1; u <= n; u++) { rep[u] = u; rnk[u] = 0; }
+  int components = n;
+  int total_cost = 0;
+  for (int i = 0; i < edges.size() && components > 1; i++) {
+    int u = e.uu.xx;
+    int v = e.uu.yy;
+
+    if (ds_find(u) != ds_find(v)) {
+      ds_union(u, v);
+      components--;
+      total_cost += e.cc;
+    }
+  }
+  return components > 1 ? oo : total_cost;
+}
diff --git a/fontes/lazy-segment-tree-alt.cpp b/fontes/lazy-segment-tree-alt.cpp
deleted file mode 100755
index ea485b3ca0d3ff1dbfe0e3db073ce808845afb5d..0000000000000000000000000000000000000000
--- a/fontes/lazy-segment-tree-alt.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-#if 0
-F="$(dirname $0)/.$(basename $0).bin"
-[ ! -f $F  -o  $F -ot $0 ] && { c++ -O2 "$0" -o "$F" || exit 1 ; }
-exec "$F" "$@"
-#endif
-
-#include <vector>
-#include <iostream>
-#include <limits>
-#include <iomanip>
-
-using namespace std;
-
-// SUM
-#define LST_OPERATION(X, Y) (X + Y)
-#define LST_NEUTRAL 0
-
-// RMQ
-// #define LST_OPERATION(X, Y) min(X, Y)
-// #define LST_NEUTRAL numeric_limits<int>::max()
-
-// RMaxQ
-// #define LST_OPERATION(X, Y) max(X, Y)
-// #define LST_NEUTRAL numeric_limits<int>::min()
-
-int op = 0;
-
-vector<int> tree(4*1E5+5, 0);
-vector<int> delta(4*1E5+5, 0);
-vector<int> origin(1E5+5, 0);
-
-void lst_recalc (int i) {
-    int l = tree[2*i] + delta[2*i];
-    int r = tree[2*i+1] + delta[2*i+1];
-    tree[i] = LST_OPERATION(l, r);
-}
-
-void lst_build (int i, int a, int b) {
-    if (a == b) {
-        tree[i] = origin[a];
-        return;
-    }
-    int m = (a+b)/2;
-    lst_build(2*i, a, m);
-    lst_build(2*i+1, m+1, b);
-    lst_recalc(i);
-}
-
-// lazy propagation
-void lst_push (int i) {
-    delta[2*i] += delta[i];
-    delta[2*i+1] += delta[i];
-    delta[i] = 0;
-}
-
-// a, b -> range wanted
-// tb, ta -> range currently iterating in tree
-void lst_add_range (int i, int a, int b, int ta, int tb, int val) {
-    // not covered
-    if (b < ta || a > tb) { return; }
-
-    // covered subtree
-    if (b >= tb && a <= ta) {
-        delta[i] += val;
-        return;
-    }
-
-    lst_push(i);
-
-    int m = (ta+tb)/2;
-    lst_add_range(2*i,   a, b, ta,  m,  val);
-    lst_add_range(2*i+1, a, b, m+1, tb, val);
-
-    lst_recalc(i);
-}
-
-int lst_query_range (int i, int a, int b, int ta, int tb) {
-    // not covered
-    if (b < ta || a > tb) { return LST_NEUTRAL; }
-
-    // covered subtree
-    if (b >= tb && a <= ta) {
-        return tree[i] + delta[i];
-    }
-
-    lst_push(i);
-
-    int m = (ta+tb)/2;
-    int r1 = lst_query_range(2*i,   a, b, ta,  m);
-    int r2 = lst_query_range(2*i+1, a, b, m+1, tb);
-
-    lst_recalc(i);
-
-    return LST_OPERATION(r1, r2);
-}
-
-void lst_print (int ta, int tb) {
-    cout << "- PRINT -" << endl;
-    cout << "Tree:  ";
-    for (int i = ta; i <= tb; i++) {
-        cout << setw(2) << tree[i] << " ";
-    }
-    cout << endl;
-    cout << "Delta: ";
-    for (int i = ta; i <= tb; i++) {
-        cout << setw(2) << delta[i] << " ";
-    }
-    cout << endl;
-}
-
-int main () {
-    int ta = 1;
-    int tb = 100000;
-    cout << "-ADD-" << endl;
-    lst_add_range(1, 1, 10, ta, tb, 1);
-    lst_add_range(1, 1, 8, ta, tb, 1);
-    lst_add_range(1, 2, 4, ta, tb, 5);
-    lst_add_range(1, 3, 8, ta, tb, 3);
-    cout << "-QUERIES-" << endl;
-
-    lst_query_range(1, 1, 1, ta, tb);
-    lst_query_range(1, 2, 2, ta, tb);
-    lst_query_range(1, 3, 3, ta, tb);
-    lst_query_range(1, 4, 4, ta, tb);
-    lst_query_range(1, 5, 5, ta, tb);
-    lst_query_range(1, 6, 6, ta, tb);
-    lst_query_range(1, 7, 7, ta, tb);
-    lst_query_range(1, 8, 8, ta, tb);
-    lst_query_range(1, 9, 9, ta, tb);
-
-    lst_query_range(1, 5, 8, ta, tb);
-    lst_query_range(1, 1, 8, ta, tb);
-    lst_query_range(1, 1, 9, ta, tb);
-
-    cout << "-QUERIES-" << endl;
-
-    lst_query_range(1, 1, 1, ta, tb);
-    lst_query_range(1, 2, 2, ta, tb);
-    lst_query_range(1, 3, 3, ta, tb);
-    lst_query_range(1, 4, 4, ta, tb);
-    lst_query_range(1, 5, 5, ta, tb);
-    lst_query_range(1, 6, 6, ta, tb);
-    lst_query_range(1, 7, 7, ta, tb);
-    lst_query_range(1, 8, 8, ta, tb);
-    lst_query_range(1, 9, 9, ta, tb);
-
-    lst_query_range(1, 5, 8, ta, tb);
-    lst_query_range(1, 1, 8, ta, tb);
-    lst_query_range(1, 1, 9, ta, tb);
-
-    cout << "-ADD-" << endl;
-    lst_add_range(1, 1, 10, ta, tb, 1);
-    lst_add_range(1, 1, 8, ta, tb, 1);
-    lst_add_range(1, 2, 4, ta, tb, 5);
-    lst_add_range(1, 3, 8, ta, tb, 3);
-    cout << "-QUERIES-" << endl;
-
-    lst_query_range(1, 1, 1, ta, tb);
-    lst_query_range(1, 2, 2, ta, tb);
-    lst_query_range(1, 3, 3, ta, tb);
-    lst_query_range(1, 4, 4, ta, tb);
-    lst_query_range(1, 5, 5, ta, tb);
-    lst_query_range(1, 6, 6, ta, tb);
-    lst_query_range(1, 7, 7, ta, tb);
-    lst_query_range(1, 8, 8, ta, tb);
-    lst_query_range(1, 9, 9, ta, tb);
-
-    lst_query_range(1, 5, 8, ta, tb);
-    lst_query_range(1, 1, 8, ta, tb);
-    lst_query_range(1, 1, 9, ta, tb);
-}
diff --git a/fontes/lazy-segment-tree.cpp b/fontes/lazy-segment-tree.cpp
index c9ea4be712f992a0aca8e9150f7ce5281e7c673c..6432e308c6acb64dbb51380051ae815e58d0bf85 100644
--- a/fontes/lazy-segment-tree.cpp
+++ b/fontes/lazy-segment-tree.cpp
@@ -1,69 +1,70 @@
-vector<T> stree(4*N), origin(N);
-vector<int> delta(4*N), setha(4*N, -1);
-
 #define LEFT 2*i
 #define RIGH 2*i+1
-#define M (ta+tb)/2
+#define MID (ta+tb)/2
 
-void recalc (int i) {
-  stree[i] = OP(stree[LEFT], stree[RIGH]);
-}
+struct node {
+  int data = 0;
 
-int build /* O(n lg n) */ (
-    int i = 1, int ta = 0, int tb = N-1) {
-  if (ta == tb) { return stree[i] = origin[ta]; }
-  build(LEFT, ta,  M);
-  build(RIGH, M+1, tb);
-  recalc(i);
-}
+  node() {};
+  node(int x) { data = x; };
 
-#define CHILD(A, OP) A[LEFT] OP; A[RIGH] OP
-void _push (int i, int ta, int tb) {
-  if (delta[i] != 0) {
-    stree[i] += FACTOR * delta[i];
-    if (ta != tb) { CHILD(delta, += delta[i]); }
-    delta[i] = 0;
-  }
+  node operator+(const node& a) {
+    node n; n.data = a.data + data; return n;
+  };
+  node operator+=(const int& a) {
+    data += a; return *this;
+  };
+};
+
+struct dlta { int add = 0, set = -1; };
 
-  if (setha[i] != -1) {
-    stree[i] = FACTOR * setha[i];
-    if (ta != tb) {
-      CHILD(setha, = setha[i]);
-      CHILD(delta, = 0);
-    }
-    setha[i] = -1;
+vector<node> stree(4*N), origin(N);
+vector<dlta> delta(4*N);
+
+void push (int i, int ta, int tb) {
+  dlta &d = delta[i];
+  dlta &l = delta[LEFT], &r = delta[RIGH];
+  if (d.add != 0) {
+    stree[i] += FACTOR * d.add;
+    if (ta != tb) { l.add += d.add; r.add += d.add; }
+    d.add = 0;
+  }
+  if (d.set != -1) {
+    stree[i] = FACTOR * d.set;
+    if (ta != tb) { l = r = { 0, d.set }; }
+    d.set = -1;
   }
 }
 
-// set_range := s/delta/setha,s/d/v
-void add_range /* O(lg n) */ (int a, int b, int d,
+node update (int i, char op, int d, int ta, int tb) {
+  if (op == '+') delta[i].add = d;
+  if (op == '=') delta[i].set = d;
+  push(i, ta, tb);
+  return stree[i];
+}
+
+node recalc (int i) {
+  return stree[i] = OP(stree[LEFT], stree[RIGH]);
+}
+
+void build /* O(n lg n) */ (
     int i = 1, int ta = 0, int tb = N-1) {
-  _push(i, ta, tb);
-  if (!(a <= tb && ta <= b)) { return; }
-  if (a <= ta && tb <= b) {
-    return delta[i] = d, _push(i, ta, tb);
-  }
-  add_range(a, b, d, LEFT, ta,  M);
-  add_range(a, b, d, RIGH, M+1, tb);
+  if (ta == tb) { stree[i] = origin[ta]; return; }
+  build(LEFT, ta,  MID);
+  build(RIGH, MID+1, tb);
   recalc(i);
 }
 
-T query_range /* O(lg n) */ (int a, int b,
+node op_range /* O(lg n) */ (int a, int b,
+    char op = '\0', int d = 0,
     int i = 1, int ta = 0, int tb = N-1) {
-  _push(i, ta, tb);
+  push(i, ta, tb);
   if (!(a <= tb && ta <= b)) { return NEUTRAL; }
-  if (a <= ta && tb <= b) { return stree[i]; }
-  auto r1 = query_range(a, b, LEFT, ta,  M);
-  auto r2 = query_range(a, b, RIGH, M+1, tb);
+  if (a <= ta && tb <= b) {
+    return update(i, op, d, ta, tb);
+  }
+  node r1 = op_range(a, b, op, d, LEFT, ta,    MID);
+  node r2 = op_range(a, b, op, d, RIGH, MID+1, tb);
+  if (op) { recalc(i); }
   return OP(r1, r2);
 }
-
-struct node {
-  array<int, 9> data {{ 0 }};
-
-  node();
-  explicit node(int x);
-
-  node operator+(const node& a) { node n; return n; };
-  node operator+=(const int& a) { return *this; };
-};
diff --git a/fontes/lcm.cpp b/fontes/lcm.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ddbbb5dcf97926ce626995ea1cb981cbfe7c02e2
--- /dev/null
+++ b/fontes/lcm.cpp
@@ -0,0 +1,3 @@
+int lcm(int a, int b) {
+  return a*b / __gcd(a, b);
+}
diff --git a/fontes/matrix-mult.cpp b/fontes/matrix-mult.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cba2df4449a676019e195128464e12a3585f9f02
--- /dev/null
+++ b/fontes/matrix-mult.cpp
@@ -0,0 +1,8 @@
+void nsq (vvll& res, vvll& n) {
+  int i = 0, j = 0;
+  ll x = (n[i][0]*res[0][j]) % mod + (n[i][1]*res[1][j]) % mod;
+  i = 0, j = 1;
+  ll y = (n[i][0]*res[0][j]) % mod + (n[i][1]*res[1][j]) % mod;
+
+  res[0][0] = x % mod; res[0][1] = y % mod;
+}
diff --git a/fontes/merge-sort.cpp b/fontes/merge-sort.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0fbd62d27442fca8ab109b55f62d24d00974b62b
--- /dev/null
+++ b/fontes/merge-sort.cpp
@@ -0,0 +1,29 @@
+vector<int> v (1e4);
+
+int merge_sort(int a, int b) {
+  // already sorted
+  if (a+1 == b) { return 0; }
+
+  int swaps = 0;
+
+  int m = a+(b-a)/2;
+  swaps += merge_sort(a, m);
+  swaps += merge_sort(m, b);
+
+  vector<int> aux (b - a);
+  int f = a, s = m;
+  for (int i = 0; i < b - a; i++) {
+    if (s < b && f < m && v[f] > v[s]) {
+      // inversion
+      swaps += m-f;
+    }
+    if ((!(s < b) || v[f] < v[s]) && f < m) {
+      aux[i] = v[f++];
+    } else {
+      aux[i] = v[s++];
+    }
+  }
+
+  copy(aux.begin(), aux.end(), v.begin()+a);
+  return swaps;
+}
diff --git a/fontes/modular-multiplicative-inverse.cpp b/fontes/modular-multiplicative-inverse.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ca62d384423fee114fc2ed34637de220a95c2c57
--- /dev/null
+++ b/fontes/modular-multiplicative-inverse.cpp
@@ -0,0 +1,4 @@
+// faster, arbitray m, x^-1 (mod m)
+int eucl_inv = (ext_gcd(x, m).x % m + m) % m;
+// slower, P is prime, x^-1 = x^(P-2) (mod P)
+int fermat_inv = fast_pow(x, P - 2);
diff --git a/fontes/neighbors.cpp b/fontes/neighbors.cpp
index 6f4ef100d2db754b9593da98defa0b5485203461..3034a0a2c6223d3fc3367839b0f1a924902481c3 100644
--- a/fontes/neighbors.cpp
+++ b/fontes/neighbors.cpp
@@ -1,14 +1,13 @@
 #include <bits/stdc++.h>
 using namespace std;
-#define all(x) x.begin(), x.end()
 
 int main() {
   cout << "4 neighbors\n";
-  vector<int> dxy = { -1, 0, 1 };
-  do {
-    if (dxy[0] == -dxy[1]) { continue; }
-    cout << dxy[0] << " " << dxy[1] << "\n";
-  } while (next_permutation(all(dxy)));
+  vector<int> dxy = { +1, 0, -1, 0, +1 };
+  for (int k = 0; k < 4; k++) {
+    int i = dxy[k], j = dxy[k+1];
+    cout << i << " " << j << "\n";
+  }
 
   cout << "\n";
 
diff --git a/fontes/prefix-sum.cpp b/fontes/prefix-sum.cpp
index 2c18065cd4faa1ad6f92d05ce7d3cef8905bc3f9..8d9132230eacd5915ad32ee68856d74c02c0b303 100644
--- a/fontes/prefix-sum.cpp
+++ b/fontes/prefix-sum.cpp
@@ -1,13 +1,11 @@
-vector<ll> prefix_sum(N, 0);
-vector<int> origin(N);
+vector<ll> prefix_sum(N+1, 0);
+vector<ll> origin(N); // origin has to be ll too
 
 void ps_build (int N) {
-  prefix_sum[0] = origin[0];
-
-  for (int i = 1; i < N; i++)
-    prefix_sum[i] = prefix_sum[i - 1] + origin[i];
+  partial_sum(origin.begin(), origin.end(), prefix_sum.begin()+1);
 }
 
+// [a, b)
 ll ps_query (int a, int b) {
-  return prefix_sum[b] - prefix_sum[a - 1];
+  return prefix_sum[b] - prefix_sum[a];
 }
diff --git a/fontes/segment-tree.cpp b/fontes/segment-tree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..580955deb90d13e96e03fe5fd75b305534eb0a18
--- /dev/null
+++ b/fontes/segment-tree.cpp
@@ -0,0 +1,37 @@
+vector<T> stree(4*N), origin(N);
+
+#define LEFT 2*i
+#define RIGH 2*i+1
+#define M (ta+tb)/2
+
+void build /* O(n lg n) */ (int N) {
+  for (int i = 0; i < N; i++)
+    stree[N + i] = origin[i];
+  for (int i = N - 1; i > 0; i--)
+    stree[i] = OP(stree[LEFT], stree[RIGH]);
+}
+
+void add /* O(lg n) */ (int i, int d) {
+  stree[i += N] = d;
+  for (i /= 2; i > 0; i /= 2)
+    stree[i] = OP(stree[LEFT], stree[RIGH]);
+}
+
+T query_range /* O(lg n) */ (int i, int j) {
+  auto left = NEUTRAL, right = NEUTRAL;
+  for (i += N, j += N; i < j; i /= 2, j /= 2) {
+    if (i & 1) left = OP(left, stree[i++]);
+    if (j & 1) right = OP(right, stree[--j]);
+  }
+  return OP(left, right);
+}
+
+struct node {
+  array<int, 9> data {{ 0 }};
+
+  node();
+  explicit node(int x);
+
+  node operator+(const node& a) { node n; return n; };
+  node operator+=(const int& a) { return *this; };
+};
diff --git a/fontes/sieve-of-eratosthenes.cpp b/fontes/sieve-of-eratosthenes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..70599090d39023aa8a3c948eb45c2321f55563f9
--- /dev/null
+++ b/fontes/sieve-of-eratosthenes.cpp
@@ -0,0 +1,9 @@
+vector<bool> sieve (1e9+1, true);
+
+void sieve_eratosthenes(int n) {
+    for (int i = 2; i * i <= n; i++) if (sieve[i]) {
+        for (int j = i * i; j <= n; j += i) {
+            sieve[j] = false;
+        }
+    }
+}
diff --git a/fontes/suffix-array-radix.cpp b/fontes/suffix-array-radix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8307ded4d8da574473e222c5b04a6ec71d3b899b
--- /dev/null
+++ b/fontes/suffix-array-radix.cpp
@@ -0,0 +1,30 @@
+vector<int> sk (n), sa (n);
+
+void build_sa(string s, int n) {
+  vector<ii> a (n);
+  for (int i = 0; i < n; i++) { a[i] = { s[i], i }; }
+  sort(a.begin(), a.end());
+  for (int i = 0; i < n; i++) { tie(sk[i], sa[i]) = a[i]; }
+
+  vector<int> nsk(n);
+  for (int i = 1, r = 0; i < n; i++)
+    nsk[sa[i]] = (sk[i-1] == sk[i] ? r : ++r);
+  sk.swap(nsk);
+
+  for (int k = 1; k < n; k *= 2) {
+    for (int i = 0; i < n; i++) { sa[i] = (sa[i]-k+n)%n; }
+
+    vector<int> nsa(n), cnt(n+1);
+    for (int x : sk) { cnt[x+1]++; }
+    for (int i = 1; i < n; i++) { cnt[i] += cnt[i-1]; }
+    for (int x : sa) { nsa[cnt[sk[x]]++] = x; }
+    sa.swap(nsa);
+
+    vector<int> nsk(n);
+    for (int i = 1, r = 0; i < n; i++)
+      nsk[sa[i]] =
+        ii(sk[sa[i-1]], sk[(sa[i-1]+k)%n]) ==
+        ii(sk[sa[i-0]], sk[(sa[i-0]+k)%n]) ? r : ++r;
+    sk.swap(nsk);
+  }
+}
diff --git a/fontes/suffix-array-sort.cpp b/fontes/suffix-array-sort.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6a894188fe182b033b240084d9ab94640ee23f9
--- /dev/null
+++ b/fontes/suffix-array-sort.cpp
@@ -0,0 +1,17 @@
+vector<int> build_sa(int n, string s) {
+  vector<int> sk (s.begin(), s.end());
+
+  vector<pair<ii, int>> a(n);
+  for (int k = 1; k < n; k *= 2) {
+    for (int i = 0; i < n; i++)
+      a[i] = { { sk[i], sk[(i+k)%n] }, i };
+    sort(a.begin(), a.end());
+    sk[a[0].ii] = 0;
+    for (int i = 1, r = 0; i < n; i++)
+      sk[a[i].ii] = a[i-1].kk == a[i].kk ? r : ++r;
+  }
+
+  vector<int> sa (n);
+  for (int i = 0; i < n; i++) { sa[i] = a[i].ii; }
+  return sa;
+}
diff --git a/fontes/tarjan.cpp b/fontes/tarjan.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dfb4680344c63e50b0cae2199cffd5862e608fc
--- /dev/null
+++ b/fontes/tarjan.cpp
@@ -0,0 +1,43 @@
+int timestamp = 0;
+vector<int> id (1e5 + 1);
+vector<int> lowlink (1e5 + 1, oo);
+vector<int> rep (1e5 + 1, 0);
+vector<int> visited (1e5 + 1, 0);
+vector<bool> on_stack (1e5 + 1, false);
+stack<int> topo_components;
+stack<int> S;
+
+int next_id = 0;
+
+void tarjan_dfs (int u) {
+  if (visited[u] == timestamp) { return; }
+  visited[u] = timestamp;
+  S.push(u); on_stack[u] = true;
+  id[u] = lowlink[u] = next_id++;
+
+  for (int v : G[u]) {
+    tarjan_dfs(v);
+    if (on_stack[v]) {
+      lowlink[u] = min(lowlink[u], lowlink[v]);
+    }
+  }
+
+  if (id[u] == lowlink[u]) {
+    int v;
+    do {
+      v = S.top(); S.pop();
+      on_stack[v] = false;
+      lowlink[v] = id[u];
+      rep[v] = u;
+    } while (v != u);
+    topo_components.push(u);
+  }
+}
+
+stack<int> tarjan (int n) {
+  timestamp++;
+  for (int i = 0; i < n; i++) {
+    tarjan_dfs(i);
+  }
+  return topo_components;
+}
diff --git a/fontes/template.cpp b/fontes/template.cpp
index db1298e6c969271ae5c89071bc883daed27dae6d..617bab689a6eac9858bfbb20173c8ad0e486510a 100644
--- a/fontes/template.cpp
+++ b/fontes/template.cpp
@@ -1,10 +1,6 @@
 #include <bits/stdc++.h>
 
 #define oo 987654321
-#define all(x) x.begin(), x.end()
-#define sz(v) int(v.size())
-#define fori(i, S, E) for (int i = S; i < E; i++)
-#define irof(i, S, E) for (int i = E - 1; i >= S; i--)
 #define clamp(x,l,u) (min(u, max(x, l)))
 
 // for coordinates
@@ -24,12 +20,6 @@
 using namespace std;
 
 typedef long long ll;
-typedef unsigned long long ull;
-typedef vector<int> vi;
-typedef pair<int, int> ii;
-typedef pair<double, double> dd;
-typedef vector<vi> vvi;
-typedef vector<dd> vdd;
 
 int main() {
   ios::sync_with_stdio(0);
diff --git a/fontes/topological-sort.cpp b/fontes/topological-sort.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5af46e467bcfe5797e4fcd4ff490a446ff6ab8b3
--- /dev/null
+++ b/fontes/topological-sort.cpp
@@ -0,0 +1,17 @@
+stack<int> S;
+vector<bool> visited (n);
+
+void dfs(int u) {
+    if (visited[u]) return;
+    visited[u] = true;
+    for (int v : G[u]) { dfs(v); }
+    S.push(u);
+}
+
+void topo_sort(int n) {
+  fill(visited.begin(), visited.begin() + n + 1, false);
+  for (int u = 1; u <= n; u++) { dfs(u); }
+  while (!S.empty()) {
+    int v = S.top(); S.pop();
+  }
+}
diff --git a/fontes/vimrc b/fontes/vimrc
index f321a90f722b924ce1afaca9874e5a3b8d8232f2..ca1c3d6f6feffcc069dd1b7fd4e7aa28421bd10c 100644
--- a/fontes/vimrc
+++ b/fontes/vimrc
@@ -1,3 +1,7 @@
-set ts=2 sw=2 cin ai et sta
+set ts=4 sw=4 cin ai et sta
 set is tm=50 nu noeb bg=dark ru cul sm
 sy on
+no! <silent> <C-l> <Esc>
+no <silent> <C-l> <Esc>
+lno <silent> <C-l> <C-c>
+tno <silent> <C-l> <Esc>
diff --git a/testes/convex-hull.cpp b/testes/convex-hull.cpp
index 5d8a33d6324ff90741880a016c8967d85fef8175..3154ef64893b698bf790a6e8153fdf54dba3cab2 100644
--- a/testes/convex-hull.cpp
+++ b/testes/convex-hull.cpp
@@ -1,7 +1,7 @@
 #include <bits/stdc++.h>
 
 #define oo 987654321
-#define all(x) x.begin(), x.end()
+#define clamp(x,l,u) (min(u, max(x, l)))
 
 // for coordinates
 #define xx first
@@ -20,97 +20,83 @@
 using namespace std;
 
 typedef long long ll;
-typedef unsigned long long ull;
-typedef vector<int> vi;
-typedef pair<int, int> ii;
-typedef pair<double, double> dd;
-typedef vector<vi> vvi;
-typedef vector<dd> vdd;
-
 
-bool ccw (dd o, dd a, dd b) {
-  return (a.xx - o.xx) * (b.yy - o.yy)
-    - (a.yy - o.yy) * (b.xx - o.xx) > 0;
-}
-bool cw (dd o, dd a, dd b) {
-  return (a.xx - o.xx) * (b.yy - o.yy)
-    - (a.yy - o.yy) * (b.xx - o.xx) < 0;
-}
-bool ccw_colinear (dd o, dd a, dd b) {
-  return (a.xx - o.xx) * (b.yy - o.yy)
-    - (a.yy - o.yy) * (b.xx - o.xx) >= 0;
-}
-bool cw_colinear (dd o, dd a, dd b) {
-  return (a.xx - o.xx) * (b.yy - o.yy)
-    - (a.yy - o.yy) * (b.xx - o.xx) <= 0;
+#define all(x) x.begin(), x.end()
+#define px real()
+#define py imag()
+#define mp make_pair
+typedef complex<double> pt;
+typedef vector<pt> vpt;
+
+int sgn (double v) { return (v > 0) - (v < 0); }
+// -1 (cw), 0 (colinear), +1 (ccw)
+int seg_ornt (pt a, pt b, pt c) {
+  return sgn((conj(b - a) * (c - a)).py);
 }
 
-vdd convex_hull_ccw /* O(n lg n) */ (vdd ps) {
-  int k = 0, i, t;
-  vdd result (sz(ps) * 2);
+vpt convex_hull_ccw /* O(n lg n) */ (vpt& ps) {
+  int k = 0, n = ps.size();
+  vpt result (n * 2);
 
-  sort(all(ps), [](dd a, dd b) {
-    return (a.xx == b.xx)
-          ? (a.yy < b.yy) : (a.xx < b.xx);
+  sort(all(ps), [](pt a, pt b) {
+    return mp(a.px, a.py) < mp(b.px, b.py);
   });
 
-  for (i = 0; i < sz(ps); i++) {
-    while (k >= 2 && !ccw( /* lower hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = 0; i < n; i++) {
+    while (k >= 2 && seg_ornt( /* lower hull */
+        result[k-2], result[k-1], ps[i]) <= 0) k--;
     result[k++] = ps[i];
   }
 
-  for (i = sz(ps) - 2, t = k + 1; i >= 0; i--) {
-    while (k >= t && !ccw( /* upper hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = n - 2, t = k + 1; i >= 0; i--) {
+    while (k >= t && seg_ornt( /* upper hull */
+        result[k-2], result[k-1], ps[i]) <= 0) k--;
     result[k++] = ps[i];
   }
 
   result.resize(k - 1);
   return result;
 }
-vdd convex_hull_cw /* O(n lg n) */ (vdd ps) {
-  int k = 0, i, t;
-  vdd result (sz(ps) * 2);
+vpt convex_hull_cw /* O(n lg n) */ (vpt& ps) {
+  int k = 0, n = ps.size();
+  vpt result (n * 2);
 
-  sort(all(ps), [](dd a, dd b) {
-    return (a.xx == b.xx)
-          ? (a.yy < b.yy) : (a.xx < b.xx);
+  sort(all(ps), [](pt a, pt b) {
+    return mp(a.px, a.py) < mp(b.px, b.py);
   });
 
-  for (i = 0; i < sz(ps); i++) {
-    while (k >= 2 && !cw( /* lower hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = 0; i < n; i++) {
+    while (k >= 2 && seg_ornt( /* lower hull */
+        result[k-2], result[k-1], ps[i]) >= 0) k--;
     result[k++] = ps[i];
   }
 
-  for (i = sz(ps) - 2, t = k + 1; i >= 0; i--) {
-    while (k >= t && !cw( /* upper hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = n - 2, t = k + 1; i >= 0; i--) {
+    while (k >= t && seg_ornt( /* upper hull */
+        result[k-2], result[k-1], ps[i]) >= 0) k--;
     result[k++] = ps[i];
   }
 
   result.resize(k - 1);
   return result;
 }
-vdd convex_hull_ccw_colinear /* O(n lg n) */ (vdd ps) {
-  int k = 0, i, t;
-  vdd result (sz(ps) * 2);
+vpt convex_hull_ccw_colinear /* O(n lg n) */ (vpt& ps) {
+  int k = 0, n = ps.size();
+  vpt result (n * 2);
 
-  sort(all(ps), [](dd a, dd b) {
-    return (a.xx == b.xx)
-          ? (a.yy < b.yy) : (a.xx < b.xx);
+  sort(all(ps), [](pt a, pt b) {
+    return mp(a.px, a.py) < mp(b.px, b.py);
   });
 
-  for (i = 0; i < sz(ps); i++) {
-    while (k >= 2 && !ccw_colinear( /* lower hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = 0; i < n; i++) {
+    while (k >= 2 && seg_ornt( /* lower hull */
+        result[k-2], result[k-1], ps[i]) < 0) k--;
     result[k++] = ps[i];
   }
 
-  for (i = sz(ps) - 2, t = k + 1; i >= 0; i--) {
-    while (k >= t && !ccw_colinear( /* upper hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = n - 2, t = k + 1; i >= 0; i--) {
+    while (k >= t && seg_ornt( /* upper hull */
+        result[k-2], result[k-1], ps[i]) < 0) k--;
     result[k++] = ps[i];
   }
 
@@ -118,24 +104,23 @@ vdd convex_hull_ccw_colinear /* O(n lg n) */ (vdd ps) {
   return result;
 }
 
-vdd convex_hull_cw_colinear /* O(n lg n) */ (vdd ps) {
-  int k = 0, i, t;
-  vdd result (sz(ps) * 2);
+vpt convex_hull_cw_colinear /* O(n lg n) */ (vpt& ps) {
+  int k = 0, n = ps.size();
+  vpt result (n * 2);
 
-  sort(all(ps), [](dd a, dd b) {
-    return (a.xx == b.xx)
-          ? (a.yy < b.yy) : (a.xx < b.xx);
+  sort(all(ps), [](pt a, pt b) {
+    return mp(a.px, a.py) < mp(b.px, b.py);
   });
 
-  for (i = 0; i < sz(ps); i++) {
-    while (k >= 2 && !cw_colinear( /* lower hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = 0; i < n; i++) {
+    while (k >= 2 && seg_ornt( /* lower hull */
+        result[k-2], result[k-1], ps[i]) > 0) k--;
     result[k++] = ps[i];
   }
 
-  for (i = sz(ps) - 2, t = k + 1; i >= 0; i--) {
-    while (k >= t && !cw_colinear( /* upper hull */
-        result[k-2], result[k-1], ps[i])) k--;
+  for (int i = n - 2, t = k + 1; i >= 0; i--) {
+    while (k >= t && seg_ornt( /* upper hull */
+        result[k-2], result[k-1], ps[i]) > 0) k--;
     result[k++] = ps[i];
   }
 
@@ -146,61 +131,61 @@ vdd convex_hull_cw_colinear /* O(n lg n) */ (vdd ps) {
 int main() {
   ios::sync_with_stdio(0);
   cin.tie(0);
-  vdd convex;
+  vpt convex;
 
   // 1 |*   *
   // 0 |* * *
   // y +-----
   //  x 0 1 2
-  vdd points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } };
+  vpt points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } };
 
   // 1 |3   2
   // 0 |0 * 1
   // y +-----
   //  x 0 1 2
   convex = convex_hull_ccw(points);
-  assert(sz(convex) == 4);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(2, 0));
-  assert(convex[2] == dd(2, 1));
-  assert(convex[3] == dd(0, 1));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(2, 0));
+  assert(convex[2] == pt(2, 1));
+  assert(convex[3] == pt(0, 1));
 
   // 1 |1   2
   // 0 |0 * 3
   // y +-----
   //  x 0 1 2
   convex = convex_hull_cw(points);
-  assert(sz(convex) == 4);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(0, 1));
-  assert(convex[2] == dd(2, 1));
-  assert(convex[3] == dd(2, 0));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(0, 1));
+  assert(convex[2] == pt(2, 1));
+  assert(convex[3] == pt(2, 0));
 
   // 1 |4   3
   // 0 |0 1 2
   // y +-----
   //  x 0 1 2
   convex = convex_hull_ccw_colinear(points);
-  assert(sz(convex) == 5);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(1, 0));
-  assert(convex[2] == dd(2, 0));
-  assert(convex[3] == dd(2, 1));
-  assert(convex[4] == dd(0, 1));
+  assert(convex.size() == 5);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(1, 0));
+  assert(convex[2] == pt(2, 0));
+  assert(convex[3] == pt(2, 1));
+  assert(convex[4] == pt(0, 1));
 
   // 1 |1   2
   // 0 |0 4 3
   // y +-----
   //  x 0 1 2
   convex = convex_hull_cw_colinear(points);
-  assert(sz(convex) == 5);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(0, 1));
-  assert(convex[2] == dd(2, 1));
-  assert(convex[3] == dd(2, 0));
-  assert(convex[4] == dd(1, 0));
+  assert(convex.size() == 5);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(0, 1));
+  assert(convex[2] == pt(2, 1));
+  assert(convex[3] == pt(2, 0));
+  assert(convex[4] == pt(1, 0));
 
-  vdd ten_by_ten_grid;
+  vpt ten_by_ten_grid;
 
   // 9 |* * * * * * * * * *
   // 8 |* * * * * * * * * *
@@ -215,7 +200,7 @@ int main() {
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   for (int i = 0; i < 100; i++) {
-    ten_by_ten_grid.pb(dd(i / 10, i % 10));
+    ten_by_ten_grid.push_back(pt(i / 10, i % 10));
   }
 
   // 9 |3 * * * * * * * * 2
@@ -231,11 +216,11 @@ int main() {
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_ccw(ten_by_ten_grid);
-  assert(sz(convex) == 4);
-  assert(convex[0] == make_pair(0., 0.));
-  assert(convex[1] == make_pair(9., 0.));
-  assert(convex[2] == make_pair(9., 9.));
-  assert(convex[3] == make_pair(0., 9.));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0., 0.));
+  assert(convex[1] == pt(9., 0.));
+  assert(convex[2] == pt(9., 9.));
+  assert(convex[3] == pt(0., 9.));
 
   // 9 |1 * * * * * * * * 2
   // 8 |* * * * * * * * * *
@@ -250,11 +235,11 @@ int main() {
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_cw(ten_by_ten_grid);
-  assert(sz(convex) == 4);
-  assert(convex[0] == make_pair(0., 0.));
-  assert(convex[1] == make_pair(0., 9.));
-  assert(convex[2] == make_pair(9., 9.));
-  assert(convex[3] == make_pair(9., 0.));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0., 0.));
+  assert(convex[1] == pt(0., 9.));
+  assert(convex[2] == pt(9., 9.));
+  assert(convex[3] == pt(9., 0.));
 
   // 9 |R Q P O N M L K J I
   // 8 |S * * * * * * * * H
@@ -269,11 +254,11 @@ int main() {
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_ccw_colinear(ten_by_ten_grid);
-  assert(sz(convex) == 36);
-  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == dd(i-0, 0.));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == dd(9., i-0));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == dd(9-i, 9.));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == dd(0., 9-i));
+  assert(convex.size() == 36);
+  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(i-0, 0.));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(9., i-0));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9-i, 9.));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(0., 9-i));
 
   // 9 |9 A B C D E F G H I
   // 8 |8 * * * * * * * * J
@@ -288,9 +273,9 @@ int main() {
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_cw_colinear(ten_by_ten_grid);
-  assert(sz(convex) == 36);
-  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == dd(0., i-0));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == dd(i-0, 9.));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == dd(9., 9-i));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == dd(9-i, 0.));
+  assert(convex.size() == 36);
+  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(0., i-0));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(i-0, 9.));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9., 9-i));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(9-i, 0.));
 }
diff --git a/testes/convex-hull.gen b/testes/convex-hull.gen
index 826733dc49aa64d9282464a15787e824ca1e9ff2..4677e3fc9c747d6987faa805d77bc0cee4fa0c7e 100755
--- a/testes/convex-hull.gen
+++ b/testes/convex-hull.gen
@@ -9,6 +9,15 @@ w
 r fontes/template.cpp
 # find main
 /int main() {/
+i
+#define all(x) x.begin(), x.end()
+#define px real()
+#define py imag()
+#define mp make_pair
+typedef complex<double> pt;
+typedef vector<pt> vpt;
+.
+/int main() {/
 # add space before main
 i
 
@@ -16,44 +25,28 @@ i
 # add convex-hull right before that space
 .r fontes/convex-hull.cpp
 ke
-# order -> ccw
-/bool ch_order/
-.,.s/ch_order/ccw/
-/bool ccw/,/^}/t-1
-/bool ccw/
-.,/^}/s/bool ccw/bool cw/
-.,/^}/s/>/</
-/bool cw/,/^}/t?bool cw?-1
-/bool cw/
-.,/^}/s/bool cw/bool ccw_colinear/
-.,/^}/s/</>=/
-/bool ccw_colinear/,/^}/t?bool ccw_colinear?-1
-/bool ccw_colinear/
-.,/^}/s/bool ccw_colinear/bool cw_colinear/
-.,/^}/s/>=/<=/
 # convex_hull -> convex_hull_ccw
-/vdd convex_hull/
+/vpt convex_hull/
 .,/^}/s/convex_hull/convex_hull_ccw/
-?vdd convex_hull_ccw?,/^}/s/\<ch_order\>/ccw/
 # copy convex_hull_ccw -> convex_hull_cw
-?vdd convex_hull_ccw?
-/vdd convex_hull_ccw/,/^}/t-1
-/vdd convex_hull_ccw/
+?vpt convex_hull_ccw?
+/vpt convex_hull_ccw/,/^}/t-1
+/vpt convex_hull_ccw/
 .,.s/convex_hull_ccw/convex_hull_cw/
-.,/^}/s/\<ccw\>/cw/
+.,/^}/s/<= 0)/>= 0)/
 # copy convex_hull_cw => convex_hull_ccw_colinear
-?vdd convex_hull_cw?
-/vdd convex_hull_cw/,/^}/t-1
-/vdd convex_hull_cw/
+?vpt convex_hull_cw?
+/vpt convex_hull_cw/,/^}/t-1
+/vpt convex_hull_cw/
 .,.s/convex_hull_cw/convex_hull_ccw_colinear/
-.,/^}/s/\<cw\>/ccw_colinear/
+.,/^}/s/>= 0)/< 0)/
 # copy convex_hull_ccw_colinear => convex_hull_cw_colinear
-?vdd convex_hull_ccw_colinear?
-/vdd convex_hull_ccw_colinear/,/^}/t-1
-/vdd convex_hull_ccw_colinear/
+?vpt convex_hull_ccw_colinear?
+/vpt convex_hull_ccw_colinear/,/^}/t-1
+/vpt convex_hull_ccw_colinear/
 .,.s/convex_hull_ccw_colinear/convex_hull_cw_colinear/
-.,/^}/s/\<ccw_colinear\>/cw_colinear/
-?vdd convex_hull_cw_colinear?i
+.,/^}/s/< 0)/> 0)/
+?vpt convex_hull_cw_colinear?i
 
 .
 # add space after
@@ -61,61 +54,61 @@ ke
 
 .
 $i
-  vdd convex;
+  vpt convex;
 
   // 1 |*   *
   // 0 |* * *
   // y +-----
   //  x 0 1 2
-  vdd points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } };
+  vpt points { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 1 }, { 2, 1 } };
 
   // 1 |3   2
   // 0 |0 * 1
   // y +-----
   //  x 0 1 2
   convex = convex_hull_ccw(points);
-  assert(sz(convex) == 4);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(2, 0));
-  assert(convex[2] == dd(2, 1));
-  assert(convex[3] == dd(0, 1));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(2, 0));
+  assert(convex[2] == pt(2, 1));
+  assert(convex[3] == pt(0, 1));
 
   // 1 |1   2
   // 0 |0 * 3
   // y +-----
   //  x 0 1 2
   convex = convex_hull_cw(points);
-  assert(sz(convex) == 4);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(0, 1));
-  assert(convex[2] == dd(2, 1));
-  assert(convex[3] == dd(2, 0));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(0, 1));
+  assert(convex[2] == pt(2, 1));
+  assert(convex[3] == pt(2, 0));
 
   // 1 |4   3
   // 0 |0 1 2
   // y +-----
   //  x 0 1 2
   convex = convex_hull_ccw_colinear(points);
-  assert(sz(convex) == 5);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(1, 0));
-  assert(convex[2] == dd(2, 0));
-  assert(convex[3] == dd(2, 1));
-  assert(convex[4] == dd(0, 1));
+  assert(convex.size() == 5);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(1, 0));
+  assert(convex[2] == pt(2, 0));
+  assert(convex[3] == pt(2, 1));
+  assert(convex[4] == pt(0, 1));
 
   // 1 |1   2
   // 0 |0 4 3
   // y +-----
   //  x 0 1 2
   convex = convex_hull_cw_colinear(points);
-  assert(sz(convex) == 5);
-  assert(convex[0] == dd(0, 0));
-  assert(convex[1] == dd(0, 1));
-  assert(convex[2] == dd(2, 1));
-  assert(convex[3] == dd(2, 0));
-  assert(convex[4] == dd(1, 0));
+  assert(convex.size() == 5);
+  assert(convex[0] == pt(0, 0));
+  assert(convex[1] == pt(0, 1));
+  assert(convex[2] == pt(2, 1));
+  assert(convex[3] == pt(2, 0));
+  assert(convex[4] == pt(1, 0));
 
-  vdd ten_by_ten_grid;
+  vpt ten_by_ten_grid;
 
   // 9 |* * * * * * * * * *
   // 8 |* * * * * * * * * *
@@ -130,7 +123,7 @@ $i
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   for (int i = 0; i < 100; i++) {
-    ten_by_ten_grid.pb(dd(i / 10, i % 10));
+    ten_by_ten_grid.push_back(pt(i / 10, i % 10));
   }
 
   // 9 |3 * * * * * * * * 2
@@ -146,11 +139,11 @@ $i
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_ccw(ten_by_ten_grid);
-  assert(sz(convex) == 4);
-  assert(convex[0] == make_pair(0., 0.));
-  assert(convex[1] == make_pair(9., 0.));
-  assert(convex[2] == make_pair(9., 9.));
-  assert(convex[3] == make_pair(0., 9.));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0., 0.));
+  assert(convex[1] == pt(9., 0.));
+  assert(convex[2] == pt(9., 9.));
+  assert(convex[3] == pt(0., 9.));
 
   // 9 |1 * * * * * * * * 2
   // 8 |* * * * * * * * * *
@@ -165,11 +158,11 @@ $i
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_cw(ten_by_ten_grid);
-  assert(sz(convex) == 4);
-  assert(convex[0] == make_pair(0., 0.));
-  assert(convex[1] == make_pair(0., 9.));
-  assert(convex[2] == make_pair(9., 9.));
-  assert(convex[3] == make_pair(9., 0.));
+  assert(convex.size() == 4);
+  assert(convex[0] == pt(0., 0.));
+  assert(convex[1] == pt(0., 9.));
+  assert(convex[2] == pt(9., 9.));
+  assert(convex[3] == pt(9., 0.));
 
   // 9 |R Q P O N M L K J I
   // 8 |S * * * * * * * * H
@@ -184,11 +177,11 @@ $i
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_ccw_colinear(ten_by_ten_grid);
-  assert(sz(convex) == 36);
-  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == dd(i-0, 0.));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == dd(9., i-0));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == dd(9-i, 9.));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == dd(0., 9-i));
+  assert(convex.size() == 36);
+  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(i-0, 0.));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(9., i-0));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9-i, 9.));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(0., 9-i));
 
   // 9 |9 A B C D E F G H I
   // 8 |8 * * * * * * * * J
@@ -203,11 +196,11 @@ $i
   // y +-------------------
   //  x 0 1 2 3 4 5 6 7 8 9
   convex = convex_hull_cw_colinear(ten_by_ten_grid);
-  assert(sz(convex) == 36);
-  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == dd(0., i-0));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == dd(i-0, 9.));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == dd(9., 9-i));
-  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == dd(9-i, 0.));
+  assert(convex.size() == 36);
+  for (int i = 0; i < 9; i++) assert(convex[i+9*0] == pt(0., i-0));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*1] == pt(i-0, 9.));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*2] == pt(9., 9-i));
+  for (int i = 0; i < 9; i++) assert(convex[i+9*3] == pt(9-i, 0.));
 .
 w
 EOF
diff --git a/testes/fenwick-2d-tree.cpp b/testes/fenwick-2d-tree.cpp
index 08ef63466b32c27423a64430b3943b08f532856b..36a24ce19420e70fffdbda0548a360592c217f52 100644
--- a/testes/fenwick-2d-tree.cpp
+++ b/testes/fenwick-2d-tree.cpp
@@ -1,7 +1,7 @@
 #include <bits/stdc++.h>
 
 #define oo 987654321
-#define all(x) x.begin(), x.end()
+#define clamp(x,l,u) (min(u, max(x, l)))
 
 // for coordinates
 #define xx first
@@ -20,17 +20,14 @@
 using namespace std;
 
 typedef long long ll;
-typedef unsigned long long ull;
-typedef vector<int> vi;
-typedef pair<int, int> ii;
-typedef pair<double, double> dd;
-typedef vector<vi> vvi;
-typedef vector<dd> vdd;
 
-const int N = 1e5 + 3;
+const int ftN = 1e3 + 3;
+const int ftM = 1e3 + 3;
+
+typedef vector<int> vi;
+typedef vector<vector<int>> vvi;
 
-int ftN = 103, ftM = 103; // O(n^2)
-vvi ftree(ftN, vector<int>(ftM, 0)); // 1-indexed
+vvi ftree(ftN, vi(ftM, 0)); // 1-indexed
 
 void ft_add /* O(lg^2 n) */ (int x,int y,int d) {
   for (; x < ftN; x += x & -x)
diff --git a/testes/fenwick-2d-tree.gen b/testes/fenwick-2d-tree.gen
index 25f901826c1c93946f7f3548cd4a8d8d75e59e44..78a4fe46051ff8bd2fbe2cae1b89ceed53aeb275 100755
--- a/testes/fenwick-2d-tree.gen
+++ b/testes/fenwick-2d-tree.gen
@@ -10,7 +10,11 @@ r fontes/template.cpp
 /int main() {/
 # add info before main
 i
-const int N = 1e5 + 3;
+const int ftN = 1e3 + 3;
+const int ftM = 1e3 + 3;
+
+typedef vector<int> vi;
+typedef vector<vector<int>> vvi;
 
 .
 # add fenwick-2d-tree right before that space
diff --git a/testes/fenwick-tree.cpp b/testes/fenwick-tree.cpp
index 08f3e96e9b97c792ae664e7d74d23ac763a0861d..acc6f1c746ee75ddb76b946357508b04f7c5fa65 100644
--- a/testes/fenwick-tree.cpp
+++ b/testes/fenwick-tree.cpp
@@ -1,7 +1,7 @@
 #include <bits/stdc++.h>
 
 #define oo 987654321
-#define all(x) x.begin(), x.end()
+#define clamp(x,l,u) (min(u, max(x, l)))
 
 // for coordinates
 #define xx first
@@ -20,64 +20,60 @@
 using namespace std;
 
 typedef long long ll;
-typedef unsigned long long ull;
-typedef vector<int> vi;
-typedef pair<int, int> ii;
-typedef pair<double, double> dd;
-typedef vector<vi> vvi;
-typedef vector<dd> vdd;
 
 const int N = 1e5 + 3;
 
-int ftN = 4*N; // O(n)
-vi ftree(ftN, 0); // 1-indexed
+typedef vector<int> vi;
+
+int ft_n = N; // O(n)
+vi ftree(ft_n, 0); // 1-indexed
 
-void ft_add /* O(lg n) */ (int i, int d) {
-  for (; i < ftN; i += i & -i)
+void add /* O(lg n) */ (int i, int d) {
+  for (; i < ft_n; i += i & -i)
     ftree[i] += d;
 }
 
-int ft_query /* O(lg n) */ (int i) {
+int query /* O(lg n) */ (int i) {
   int sum = 0;
   for (; i > 0; i -= i & -i)
     sum += ftree[i];
   return sum;
 }
 
-// add + range_query, ft_query_upto := ft_query
-int ft_range_sum /* O(lg n) */ (int i, int j) {
-  return ft_query(j) - ft_query(i - 1);
+// 1: add + range_sum, query is query_upto
+int range_query /* O(lg n) */ (int i, int j) {
+  return query(j) - query(i - 1);
 }
 
-// range_add + query, ft_query := ft_query
-void ft_range_add (int a, int b, int d) {
-    ft_add(a, d);
-    ft_add(b + 1, -d);
+// 2: range_add + query, query is query
+void range_add (int a, int b, int d) {
+    add(a, d);
+    add(b + 1, -d);
 }
 
 int main() {
   ios::sync_with_stdio(0);
   cin.tie(0);
-  ft_add(1, 1);
-  ft_add(2, 3);
-  ft_add(3, 5);
-  ft_add(4, 6);
-  ft_add(5, 6);
-  ft_add(6, 9);
-  ft_add(7, 8);
-  ft_add(8, 6);
-  ft_add(9, 2);
+  add(1, 1);
+  add(2, 3);
+  add(3, 5);
+  add(4, 6);
+  add(5, 6);
+  add(6, 9);
+  add(7, 8);
+  add(8, 6);
+  add(9, 2);
 
-  assert(ft_range_sum(1, 1) == 1);
-  assert(ft_range_sum(2, 2) == 3);
-  assert(ft_range_sum(3, 3) == 5);
-  assert(ft_range_sum(4, 4) == 6);
-  assert(ft_range_sum(5, 5) == 6);
-  assert(ft_range_sum(6, 6) == 9);
-  assert(ft_range_sum(7, 7) == 8);
-  assert(ft_range_sum(8, 8) == 6);
-  assert(ft_range_sum(9, 9) == 2);
-  assert(ft_range_sum(5, 8) == 6+9+8+6);
-  assert(ft_range_sum(1, 8) == 1+3+5+6+6+9+8+6);
-  assert(ft_range_sum(1, 9) == 1+3+5+6+6+9+8+6+2);
+  assert(range_query(1, 1) == 1);
+  assert(range_query(2, 2) == 3);
+  assert(range_query(3, 3) == 5);
+  assert(range_query(4, 4) == 6);
+  assert(range_query(5, 5) == 6);
+  assert(range_query(6, 6) == 9);
+  assert(range_query(7, 7) == 8);
+  assert(range_query(8, 8) == 6);
+  assert(range_query(9, 9) == 2);
+  assert(range_query(5, 8) == 6+9+8+6);
+  assert(range_query(1, 8) == 1+3+5+6+6+9+8+6);
+  assert(range_query(1, 9) == 1+3+5+6+6+9+8+6+2);
 }
diff --git a/testes/fenwick-tree.gen b/testes/fenwick-tree.gen
index 3efa7457757798f3a26c09a5c573a26870cd531d..52356704bac1927192ef4c56fff9122c9945f70a 100755
--- a/testes/fenwick-tree.gen
+++ b/testes/fenwick-tree.gen
@@ -12,6 +12,8 @@ r fontes/template.cpp
 i
 const int N = 1e5 + 3;
 
+typedef vector<int> vi;
+
 .
 # add fenwick-tree right before that space
 .r fontes/fenwick-tree.cpp
@@ -20,28 +22,28 @@ a
 
 .
 $i
-  ft_add(1, 1);
-  ft_add(2, 3);
-  ft_add(3, 5);
-  ft_add(4, 6);
-  ft_add(5, 6);
-  ft_add(6, 9);
-  ft_add(7, 8);
-  ft_add(8, 6);
-  ft_add(9, 2);
+  add(1, 1);
+  add(2, 3);
+  add(3, 5);
+  add(4, 6);
+  add(5, 6);
+  add(6, 9);
+  add(7, 8);
+  add(8, 6);
+  add(9, 2);
 
-  assert(ft_range_sum(1, 1) == 1);
-  assert(ft_range_sum(2, 2) == 3);
-  assert(ft_range_sum(3, 3) == 5);
-  assert(ft_range_sum(4, 4) == 6);
-  assert(ft_range_sum(5, 5) == 6);
-  assert(ft_range_sum(6, 6) == 9);
-  assert(ft_range_sum(7, 7) == 8);
-  assert(ft_range_sum(8, 8) == 6);
-  assert(ft_range_sum(9, 9) == 2);
-  assert(ft_range_sum(5, 8) == 6+9+8+6);
-  assert(ft_range_sum(1, 8) == 1+3+5+6+6+9+8+6);
-  assert(ft_range_sum(1, 9) == 1+3+5+6+6+9+8+6+2);
+  assert(range_query(1, 1) == 1);
+  assert(range_query(2, 2) == 3);
+  assert(range_query(3, 3) == 5);
+  assert(range_query(4, 4) == 6);
+  assert(range_query(5, 5) == 6);
+  assert(range_query(6, 6) == 9);
+  assert(range_query(7, 7) == 8);
+  assert(range_query(8, 8) == 6);
+  assert(range_query(9, 9) == 2);
+  assert(range_query(5, 8) == 6+9+8+6);
+  assert(range_query(1, 8) == 1+3+5+6+6+9+8+6);
+  assert(range_query(1, 9) == 1+3+5+6+6+9+8+6+2);
 .
 w
 EOF
diff --git a/testes/hld-ps.cpp b/testes/hld-ps.cpp
index 42fbafa10ebb9c43b472fa89123ca5998c0fa56d..106eae87db389c6e09c93c8d0de2f12634922841 100644
--- a/testes/hld-ps.cpp
+++ b/testes/hld-ps.cpp
@@ -1,7 +1,7 @@
 #include <bits/stdc++.h>
 
 #define oo 987654321
-#define all(x) x.begin(), x.end()
+#define clamp(x,l,u) (min(u, max(x, l)))
 
 // for coordinates
 #define xx first
@@ -20,29 +20,26 @@
 using namespace std;
 
 typedef long long ll;
-typedef unsigned long long ull;
-typedef vector<int> vi;
-typedef pair<int, int> ii;
-typedef pair<double, double> dd;
-typedef vector<vi> vvi;
-typedef vector<dd> vdd;
 
 const int N = 1e5 + 3;
 
-vector<ll> prefix_sum(N, 0);
-vector<int> origin(N);
+vector<ll> prefix_sum(N+1, 0);
+vector<ll> origin(N); // origin has to be ll too
 
 void ps_build (int N) {
-  prefix_sum[0] = origin[0];
-
-  for (int i = 1; i < N; i++)
-    prefix_sum[i] = prefix_sum[i - 1] + origin[i];
+  partial_sum(origin.begin(), origin.end(), prefix_sum.begin()+1);
 }
 
+// [a, b)
 ll ps_query (int a, int b) {
-  return prefix_sum[b] - prefix_sum[a - 1];
+  return prefix_sum[b] - prefix_sum[a];
+}
+
+ll ps_query_inclusive (int a, int b) {
+  return ps_query(a, b+1);
 }
 
+typedef vector<ll> vi;
 typedef pair<int, long> il;
 typedef vector<vector<il>> vvil;
 
@@ -95,13 +92,13 @@ ll hld_sum /* O(lg^2 n) */ (int u, int v) {
   ll answer = 0;
   for (; hds[u] != hds[v]; v = parents[hds[v]]) {
     if (heights[hds[u]] > heights[hds[v]]) swap(u, v);
-    ll path_sum = ps_query(ixs[hds[v]], ixs[v]);
+    ll path_sum = ps_query_inclusive(ixs[hds[v]], ixs[v]);
     answer += path_sum;
   }
   if (heights[u] > heights[v]) swap(u, v);
 
   // Remove +1 if values are associated with vertices
-  return answer + ps_query(ixs[u] + 1, ixs[v]);
+  return answer + ps_query_inclusive(ixs[u] + 1, ixs[v]);
 }
 
 int main() {
diff --git a/testes/hld-ps.gen b/testes/hld-ps.gen
index fa11d6ab8233a2e3dfab3aeb8bfcc70c5689b5ea..6cdaf50706a6ccddac65a4a0659849f3966d2b7a 100755
--- a/testes/hld-ps.gen
+++ b/testes/hld-ps.gen
@@ -18,10 +18,15 @@ const int N = 1e5 + 3;
 # add space after
 a
 
+ll ps_query_inclusive (int a, int b) {
+  return ps_query(a, b+1);
+}
+
 .
 # add content before
 i
 
+typedef vector<ll> vi;
 typedef pair<int, long> il;
 typedef vector<vector<il>> vvil;
 
@@ -60,7 +65,7 @@ a
 .
 # patch hld_query
 /ll hld_sum /
-.,+12s/query(/ps_query(/
+.,+12s/query(/ps_query_inclusive(/
 $i
 
   int N;
diff --git a/testes/lazy-segment-tree.cpp b/testes/lazy-segment-tree.cpp
index 17ad7718821e98a2dc53084c757582c1c4f74fc7..3ece8f40736ff593e240a51297b4e2dda82bca2a 100644
--- a/testes/lazy-segment-tree.cpp
+++ b/testes/lazy-segment-tree.cpp
@@ -1,7 +1,7 @@
 #include <bits/stdc++.h>
 
 #define oo 987654321
-#define all(x) x.begin(), x.end()
+#define clamp(x,l,u) (min(u, max(x, l)))
 
 // for coordinates
 #define xx first
@@ -20,177 +20,156 @@
 using namespace std;
 
 typedef long long ll;
-typedef unsigned long long ull;
-typedef vector<int> vi;
-typedef pair<int, int> ii;
-typedef pair<double, double> dd;
-typedef vector<vi> vvi;
-typedef vector<dd> vdd;
-
-#define LST_T int
-#define LST_OP(X, Y) (X + Y)
-#define LST_NEUTRAL 0
-#define LST_FACTOR (tb - ta + 1)
 
-const int N = 1e5 + 3;
+#define OP(X, Y) (X + Y)
+#define NEUTRAL 0
+#define FACTOR (tb - ta + 1)
 
-vector<LST_T> stree(4*N), origin(N);
-vector<int> delta(4*N), setha(4*N, -1);
+const int N = 1e5 + 3;
 
 #define LEFT 2*i
 #define RIGH 2*i+1
-#define M (ta+tb)/2
+#define MID (ta+tb)/2
 
-void lst_recalc (int i) {
-  stree[i] = LST_OP(stree[LEFT], stree[RIGH]);
-}
+struct node {
+  int data = 0;
 
-void lst_build /* O(n lg n) */ (
-    function<LST_T(int)> fn = [](int i) {
-      return origin[i];
-    }, int i = 1, int ta = 0, int tb = N-1) {
-  if (ta == tb) { stree[i] = origin[ta]; return; }
-  lst_build(fn, LEFT, ta,  M);
-  lst_build(fn, RIGH, M+1, tb);
-  lst_recalc(i);
-}
+  node() {};
+  node(int x) { data = x; };
 
-#define CHILD(A, OP) A[LEFT] OP; A[RIGH] OP
-void _lst_push (int i, int ta, int tb) {
-  if (delta[i] != 0) {
-    stree[i] += LST_FACTOR * delta[i];
-    if (ta != tb) { CHILD(delta, += delta[i]); }
-    delta[i] = 0;
-  }
+  node operator+(const node& a) {
+    node n; n.data = a.data + data; return n;
+  };
+  node operator+=(const int& a) {
+    data += a; return *this;
+  };
+};
+
+struct dlta { int add = 0, set = -1; };
 
-  if (setha[i] != -1) {
-    stree[i] = LST_FACTOR * setha[i];
-    if (ta != tb) {
-      CHILD(setha, = setha[i]);
-      CHILD(delta, = 0);
-    }
-    setha[i] = -1;
+vector<node> stree(4*N), origin(N);
+vector<dlta> delta(4*N);
+
+void push (int i, int ta, int tb) {
+  dlta &d = delta[i];
+  dlta &l = delta[LEFT], &r = delta[RIGH];
+  if (d.add != 0) {
+    stree[i] += FACTOR * d.add;
+    if (ta != tb) { l.add += d.add; r.add += d.add; }
+    d.add = 0;
+  }
+  if (d.set != -1) {
+    stree[i] = FACTOR * d.set;
+    if (ta != tb) { l = r = { 0, d.set }; }
+    d.set = -1;
   }
 }
 
-// lst_set_range := s/delta/setha,s/d/v
-void lst_add_range /* O(lg n) */ (int a, int b, int d,
-    int i = 1, int ta = 0, int tb = N-1) {
-  _lst_push(i, ta, tb);
-  if (b < ta || a > tb) { return; }
-  if (b >= tb && a <= ta) {
-    return delta[i] = d, _lst_push(i, ta, tb);
-  }
-  lst_add_range(a, b, d, LEFT, ta,  M);
-  lst_add_range(a, b, d, RIGH, M+1, tb);
-  lst_recalc(i);
+node update (int i, char op, int d, int ta, int tb) {
+  if (op == '+') delta[i].add = d;
+  if (op == '=') delta[i].set = d;
+  push(i, ta, tb);
+  return stree[i];
 }
 
-void lst_set_range /* O(lg n) */ (int a, int b, int v,
-    int i = 1, int ta = 0, int tb = N-1) {
-  _lst_push(i, ta, tb);
-  if (b < ta || a > tb) { return; }
-  if (b >= tb && a <= ta) {
-    return setha[i] = v, _lst_push(i, ta, tb);
-  }
-  lst_set_range(a, b, v, LEFT, ta,  M);
-  lst_set_range(a, b, v, RIGH, M+1, tb);
-  lst_recalc(i);
+node recalc (int i) {
+  return stree[i] = OP(stree[LEFT], stree[RIGH]);
 }
 
-LST_T lst_query_range /* O(lg n) */ (int a, int b,
+void build /* O(n lg n) */ (
     int i = 1, int ta = 0, int tb = N-1) {
-  _lst_push(i, ta, tb);
-  if (b < ta || a > tb) { return LST_NEUTRAL; }
-  if (b >= tb && a <= ta) { return stree[i]; }
-  auto r1 = lst_query_range(a, b, LEFT, ta,  M);
-  auto r2 = lst_query_range(a, b, RIGH, M+1, tb);
-  return LST_OP(r1, r2);
+  if (ta == tb) { stree[i] = origin[ta]; return; }
+  build(LEFT, ta,  MID);
+  build(RIGH, MID+1, tb);
+  recalc(i);
 }
 
-struct node {
-  array<int, 9> data {{ 0 }};
-
-  node();
-  explicit node(int x);
-
-  node operator+(const node& a) { node n; return n; };
-  node operator+=(const int& a) { return *this; };
-};
-
+node op_range /* O(lg n) */ (int a, int b,
+    char op = '\0', int d = 0,
+    int i = 1, int ta = 0, int tb = N-1) {
+  push(i, ta, tb);
+  if (!(a <= tb && ta <= b)) { return NEUTRAL; }
+  if (a <= ta && tb <= b) {
+    return update(i, op, d, ta, tb);
+  }
+  node r1 = op_range(a, b, op, d, LEFT, ta,    MID);
+  node r2 = op_range(a, b, op, d, RIGH, MID+1, tb);
+  if (op) { recalc(i); }
+  return OP(r1, r2);
+}
 int main() {
   ios::sync_with_stdio(0);
   cin.tie(0);
-  lst_add_range(1, 10, 1);
-  lst_add_range(1,  8, 1);
-  lst_add_range(2,  4, 5);
-  lst_add_range(3,  8, 3);
-
-  lst_set_range(1, 10, 0);
-
-  assert(lst_query_range(1, 1) == 0);
-  assert(lst_query_range(2, 2) == 0);
-  assert(lst_query_range(3, 3) == 0);
-  assert(lst_query_range(4, 4) == 0);
-  assert(lst_query_range(5, 5) == 0);
-  assert(lst_query_range(6, 6) == 0);
-  assert(lst_query_range(7, 7) == 0);
-  assert(lst_query_range(8, 8) == 0);
-  assert(lst_query_range(9, 9) == 0);
-
-  assert(lst_query_range(5, 8) == 0);
-  assert(lst_query_range(1, 8) == 0);
-  assert(lst_query_range(1, 9) == 0);
-
-  lst_add_range(1, 10, 1);
-  lst_add_range(1,  8, 1);
-  lst_add_range(2,  4, 5);
-  lst_add_range(3,  8, 3);
-
-  assert(lst_query_range(1, 1) == 2);
-  assert(lst_query_range(2, 2) == 7);
-  assert(lst_query_range(3, 3) == 10);
-  assert(lst_query_range(4, 4) == 10);
-  assert(lst_query_range(5, 5) == 5);
-  assert(lst_query_range(6, 6) == 5);
-  assert(lst_query_range(7, 7) == 5);
-  assert(lst_query_range(8, 8) == 5);
-  assert(lst_query_range(9, 9) == 1);
-
-  assert(lst_query_range(5, 8) == 20);
-  assert(lst_query_range(1, 8) == 49);
-  assert(lst_query_range(1, 9) == 50);
-
-  lst_add_range(1, 10, 1);
-
-  assert(lst_query_range(1, 1) == 3);
-  assert(lst_query_range(2, 2) == 8);
-  assert(lst_query_range(3, 3) == 11);
-  assert(lst_query_range(4, 4) == 11);
-  assert(lst_query_range(5, 5) == 6);
-  assert(lst_query_range(6, 6) == 6);
-  assert(lst_query_range(7, 7) == 6);
-  assert(lst_query_range(8, 8) == 6);
-  assert(lst_query_range(9, 9) == 2);
-
-  assert(lst_query_range(5, 8) == 24);
-  assert(lst_query_range(1, 8) == 57);
-  assert(lst_query_range(1, 9) == 59);
-
-  lst_set_range(1, 7, 0);
-
-  assert(lst_query_range(1, 1) == 0);
-  assert(lst_query_range(2, 2) == 0);
-  assert(lst_query_range(3, 3) == 0);
-  assert(lst_query_range(4, 4) == 0);
-  assert(lst_query_range(5, 5) == 0);
-  assert(lst_query_range(6, 6) == 0);
-  assert(lst_query_range(7, 7) == 0);
-  assert(lst_query_range(8, 8) == 6);
-  assert(lst_query_range(9, 9) == 2);
-
-  assert(lst_query_range(5, 7) == 0);
-  assert(lst_query_range(5, 8) == 6);
-  assert(lst_query_range(1, 8) == 6);
-  assert(lst_query_range(1, 9) == 8);
+  op_range(1, 10, '+', 1);
+  op_range(1,  8, '+', 1);
+  op_range(2,  4, '+', 5);
+  op_range(3,  8, '+', 3);
+
+  op_range(1, 10, '=', 0);
+
+  assert(op_range(1, 1).data == 0);
+  assert(op_range(2, 2).data == 0);
+  assert(op_range(3, 3).data == 0);
+  assert(op_range(4, 4).data == 0);
+  assert(op_range(5, 5).data == 0);
+  assert(op_range(6, 6).data == 0);
+  assert(op_range(7, 7).data == 0);
+  assert(op_range(8, 8).data == 0);
+  assert(op_range(9, 9).data == 0);
+
+  assert(op_range(5, 8).data == 0);
+  assert(op_range(1, 8).data == 0);
+  assert(op_range(1, 9).data == 0);
+
+  op_range(1, 10, '+', 1);
+  op_range(1,  8, '+', 1);
+  op_range(2,  4, '+', 5);
+  op_range(3,  8, '+', 3);
+
+  assert(op_range(1, 1).data == 2);
+  assert(op_range(2, 2).data == 7);
+  assert(op_range(3, 3).data == 10);
+  assert(op_range(4, 4).data == 10);
+  assert(op_range(5, 5).data == 5);
+  assert(op_range(6, 6).data == 5);
+  assert(op_range(7, 7).data == 5);
+  assert(op_range(8, 8).data == 5);
+  assert(op_range(9, 9).data == 1);
+
+  assert(op_range(5, 8).data == 20);
+  assert(op_range(1, 8).data == 49);
+  assert(op_range(1, 9).data == 50);
+
+  op_range(1, 10, '+', 1);
+
+  assert(op_range(1, 1).data == 3);
+  assert(op_range(2, 2).data == 8);
+  assert(op_range(3, 3).data == 11);
+  assert(op_range(4, 4).data == 11);
+  assert(op_range(5, 5).data == 6);
+  assert(op_range(6, 6).data == 6);
+  assert(op_range(7, 7).data == 6);
+  assert(op_range(8, 8).data == 6);
+  assert(op_range(9, 9).data == 2);
+
+  assert(op_range(5, 8).data == 24);
+  assert(op_range(1, 8).data == 57);
+  assert(op_range(1, 9).data == 59);
+
+  op_range(1, 7, '=', 0);
+
+  assert(op_range(1, 1).data == 0);
+  assert(op_range(2, 2).data == 0);
+  assert(op_range(3, 3).data == 0);
+  assert(op_range(4, 4).data == 0);
+  assert(op_range(5, 5).data == 0);
+  assert(op_range(6, 6).data == 0);
+  assert(op_range(7, 7).data == 0);
+  assert(op_range(8, 8).data == 6);
+  assert(op_range(9, 9).data == 2);
+
+  assert(op_range(5, 7).data == 0);
+  assert(op_range(5, 8).data == 6);
+  assert(op_range(1, 8).data == 6);
+  assert(op_range(1, 9).data == 8);
 }
diff --git a/testes/lazy-segment-tree.gen b/testes/lazy-segment-tree.gen
index 6fa6f77ed0747d63c0b0255c70655c62e59c2035..38d6cf05573941d2c88bf852ff726062863a6537 100755
--- a/testes/lazy-segment-tree.gen
+++ b/testes/lazy-segment-tree.gen
@@ -14,10 +14,9 @@ r fontes/template.cpp
 #
 # add info before main
 i
-#define LST_T int
-#define LST_OP(X, Y) (X + Y)
-#define LST_NEUTRAL 0
-#define LST_FACTOR (tb - ta + 1)
+#define OP(X, Y) (X + Y)
+#define NEUTRAL 0
+#define FACTOR (tb - ta + 1)
 
 const int N = 1e5 + 3;
 
@@ -25,94 +24,79 @@ const int N = 1e5 + 3;
 #
 # add fenwick-tree right before that space
 .r fontes/lazy-segment-tree.cpp
-ke
-/void lst_add_range/
-/void lst_add_range/,/^}/t-1
-/void lst_add_range/
-.,/^}/s/lst_add_range/lst_set_range/
-?void lst_set_range?,/^}/s/\<d\>/v/
-?void lst_set_range?,/^}/s/\<delta\>/setha/
-?void lst_set_range?i
-
-.
-#
-# add space after
-'ea
-
-.
 $i
-  lst_add_range(1, 10, 1);
-  lst_add_range(1,  8, 1);
-  lst_add_range(2,  4, 5);
-  lst_add_range(3,  8, 3);
-
-  lst_set_range(1, 10, 0);
-
-  assert(lst_query_range(1, 1) == 0);
-  assert(lst_query_range(2, 2) == 0);
-  assert(lst_query_range(3, 3) == 0);
-  assert(lst_query_range(4, 4) == 0);
-  assert(lst_query_range(5, 5) == 0);
-  assert(lst_query_range(6, 6) == 0);
-  assert(lst_query_range(7, 7) == 0);
-  assert(lst_query_range(8, 8) == 0);
-  assert(lst_query_range(9, 9) == 0);
-
-  assert(lst_query_range(5, 8) == 0);
-  assert(lst_query_range(1, 8) == 0);
-  assert(lst_query_range(1, 9) == 0);
-
-  lst_add_range(1, 10, 1);
-  lst_add_range(1,  8, 1);
-  lst_add_range(2,  4, 5);
-  lst_add_range(3,  8, 3);
-
-  assert(lst_query_range(1, 1) == 2);
-  assert(lst_query_range(2, 2) == 7);
-  assert(lst_query_range(3, 3) == 10);
-  assert(lst_query_range(4, 4) == 10);
-  assert(lst_query_range(5, 5) == 5);
-  assert(lst_query_range(6, 6) == 5);
-  assert(lst_query_range(7, 7) == 5);
-  assert(lst_query_range(8, 8) == 5);
-  assert(lst_query_range(9, 9) == 1);
-
-  assert(lst_query_range(5, 8) == 20);
-  assert(lst_query_range(1, 8) == 49);
-  assert(lst_query_range(1, 9) == 50);
-
-  lst_add_range(1, 10, 1);
-
-  assert(lst_query_range(1, 1) == 3);
-  assert(lst_query_range(2, 2) == 8);
-  assert(lst_query_range(3, 3) == 11);
-  assert(lst_query_range(4, 4) == 11);
-  assert(lst_query_range(5, 5) == 6);
-  assert(lst_query_range(6, 6) == 6);
-  assert(lst_query_range(7, 7) == 6);
-  assert(lst_query_range(8, 8) == 6);
-  assert(lst_query_range(9, 9) == 2);
-
-  assert(lst_query_range(5, 8) == 24);
-  assert(lst_query_range(1, 8) == 57);
-  assert(lst_query_range(1, 9) == 59);
-
-  lst_set_range(1, 7, 0);
-
-  assert(lst_query_range(1, 1) == 0);
-  assert(lst_query_range(2, 2) == 0);
-  assert(lst_query_range(3, 3) == 0);
-  assert(lst_query_range(4, 4) == 0);
-  assert(lst_query_range(5, 5) == 0);
-  assert(lst_query_range(6, 6) == 0);
-  assert(lst_query_range(7, 7) == 0);
-  assert(lst_query_range(8, 8) == 6);
-  assert(lst_query_range(9, 9) == 2);
-
-  assert(lst_query_range(5, 7) == 0);
-  assert(lst_query_range(5, 8) == 6);
-  assert(lst_query_range(1, 8) == 6);
-  assert(lst_query_range(1, 9) == 8);
+  op_range(1, 10, '+', 1);
+  op_range(1,  8, '+', 1);
+  op_range(2,  4, '+', 5);
+  op_range(3,  8, '+', 3);
+
+  op_range(1, 10, '=', 0);
+
+  assert(op_range(1, 1).data == 0);
+  assert(op_range(2, 2).data == 0);
+  assert(op_range(3, 3).data == 0);
+  assert(op_range(4, 4).data == 0);
+  assert(op_range(5, 5).data == 0);
+  assert(op_range(6, 6).data == 0);
+  assert(op_range(7, 7).data == 0);
+  assert(op_range(8, 8).data == 0);
+  assert(op_range(9, 9).data == 0);
+
+  assert(op_range(5, 8).data == 0);
+  assert(op_range(1, 8).data == 0);
+  assert(op_range(1, 9).data == 0);
+
+  op_range(1, 10, '+', 1);
+  op_range(1,  8, '+', 1);
+  op_range(2,  4, '+', 5);
+  op_range(3,  8, '+', 3);
+
+  assert(op_range(1, 1).data == 2);
+  assert(op_range(2, 2).data == 7);
+  assert(op_range(3, 3).data == 10);
+  assert(op_range(4, 4).data == 10);
+  assert(op_range(5, 5).data == 5);
+  assert(op_range(6, 6).data == 5);
+  assert(op_range(7, 7).data == 5);
+  assert(op_range(8, 8).data == 5);
+  assert(op_range(9, 9).data == 1);
+
+  assert(op_range(5, 8).data == 20);
+  assert(op_range(1, 8).data == 49);
+  assert(op_range(1, 9).data == 50);
+
+  op_range(1, 10, '+', 1);
+
+  assert(op_range(1, 1).data == 3);
+  assert(op_range(2, 2).data == 8);
+  assert(op_range(3, 3).data == 11);
+  assert(op_range(4, 4).data == 11);
+  assert(op_range(5, 5).data == 6);
+  assert(op_range(6, 6).data == 6);
+  assert(op_range(7, 7).data == 6);
+  assert(op_range(8, 8).data == 6);
+  assert(op_range(9, 9).data == 2);
+
+  assert(op_range(5, 8).data == 24);
+  assert(op_range(1, 8).data == 57);
+  assert(op_range(1, 9).data == 59);
+
+  op_range(1, 7, '=', 0);
+
+  assert(op_range(1, 1).data == 0);
+  assert(op_range(2, 2).data == 0);
+  assert(op_range(3, 3).data == 0);
+  assert(op_range(4, 4).data == 0);
+  assert(op_range(5, 5).data == 0);
+  assert(op_range(6, 6).data == 0);
+  assert(op_range(7, 7).data == 0);
+  assert(op_range(8, 8).data == 6);
+  assert(op_range(9, 9).data == 2);
+
+  assert(op_range(5, 7).data == 0);
+  assert(op_range(5, 8).data == 6);
+  assert(op_range(1, 8).data == 6);
+  assert(op_range(1, 9).data == 8);
 .
 w
 EOF