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