From ad6dc0200d22ec258a468bbaf90b5e974689bbe6 Mon Sep 17 00:00:00 2001 From: emoreira Date: Wed, 28 Aug 2024 16:28:07 -0300 Subject: [PATCH 1/4] codigo segbeats nova --- .../Segment-Tree/Segment-Tree-Beats/README.md | 3 +- .../Segment-Tree-Beats/seg_tree_beats.cpp | 200 ++++++++++++------ 2 files changed, 136 insertions(+), 67 deletions(-) diff --git a/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md b/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md index b579edab..486ae4f2 100644 --- a/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md +++ b/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md @@ -1,3 +1,4 @@ # [Segment Tree Beats](seg_tree_beats.cpp) -Segment Tree que suporta update de maximo e query de soma. A construção é $\mathcal{O}(n)$ e as operações de consulta e update são $\mathcal{O}(\log n)$. +Segment Tree que suporta update de maximo, update de minimo, update de soma, e query de soma. A construção é $\mathcal{O}(n)$ e as operações de consulta e update são $\mathcal{O}(\log^2 n)$. +**Obs**: Se não usar o update de soma, a complexidade é das operações é $\mathcal{O}(\log n)$ diff --git a/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/seg_tree_beats.cpp b/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/seg_tree_beats.cpp index 4ad50e95..78200997 100644 --- a/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/seg_tree_beats.cpp +++ b/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/seg_tree_beats.cpp @@ -1,83 +1,151 @@ -const int INF = 1e9; - -struct Node { - int m1 = INF, m2 = INF, cont = 0, lazy = 0; - ll soma = 0; - void set(int v) { - m1 = v; - cont = 1; - soma = v; - } - void merge(Node a, Node b) { - m1 = min(a.m1, b.m1); - m2 = INF; - if (a.m1 != b.m1) m2 = min(m2, max(a.m1, b.m1)); - if (a.m2 != m1) m2 = min(m2, a.m2); - if (b.m2 != m1) m2 = min(m2, b.m2); - cont = (a.m1 == m1 ? a.cont : 0) + (b.m1 == m1 ? b.cont : 0); - soma = a.soma + b.soma; +const ll INF = 1e18; +struct node { + ll mi, smi, mx, smx, sum, lazy; + int fmi, fmx; + node() { + mi = smi = INF; + mx = smx = -INF; + fmi = 0, fmx = 0, sum = 0, lazy = 0; + } + node(ll val) { + mi = mx = sum = val; + smi = INF, smx = -INF; + fmx = fmi = 1; + lazy = 0; } }; -struct SegTreeBeats { - int n, q; - vector t; - inline int lc(int n) { return 2 * n + 1; } - inline int rc(int n) { return 2 * n + 2; } - void push(int n, int esq, int dir) { - if (t[n].lazy <= t[n].m1) return; - t[n].soma += (ll)abs(t[n].m1 - t[n].lazy) * t[n].cont; - t[n].m1 = t[n].lazy; - if (esq != dir) { - t[lc(n)].lazy = max(t[lc(n)].lazy, t[n].lazy); - t[rc(n)].lazy = max(t[rc(n)].lazy, t[n].lazy); - } - t[n].lazy = 0; - } - void build(int n, int esq, int dir, const vector &v) { - if (esq == dir) { - t[n].set(v[esq]); - } else { - int mid = (esq + dir) / 2; - build(lc(n), esq, mid, v); - build(rc(n), mid + 1, dir, v); - t[n].merge(t[lc(n)], t[rc(n)]); - } +node operator+(node a, node b) { + node ret; + ret.sum = a.sum + b.sum; + if (a.mi == b.mi) { + ret.mi = a.mi; + ret.fmi = a.fmi + b.fmi; + ret.smi = min(a.smi, b.smi); + } else if (a.mi < b.mi) { + ret.mi = a.mi; + ret.fmi = a.fmi; + ret.smi = min(a.smi, b.mi); + } else { + ret.mi = b.mi; + ret.fmi = b.fmi; + ret.smi = min(b.smi, a.mi); + } + if (a.mx == b.mx) { + ret.mx = a.mx; + ret.fmx = a.fmx + b.fmx; + ret.smx = max(a.smx, b.smx); + } else if (a.mx > b.mx) { + ret.mx = a.mx; + ret.fmx = a.fmx; + ret.smx = max(b.mx, a.smx); + } else { + ret.fmx = b.fmx; + ret.mx = b.mx; + ret.smx = max(a.mx, b.smx); } + return ret; +} + +struct SegBeats { + vector t; + int n; void build(int _n) { // pra construir com tamanho, mas vazia n = _n; - t.assign(n * 4, Node()); + t.assign(n * 4, node()); } void build(const vector &v) { // pra construir com vector n = (int)v.size(); - t.assign(n * 4, Node()); - build(0, 0, n - 1, v); + t.assign(n * 4, node()); + build(1, 0, n - 1, v); } void build(ll *bg, ll *en) { // pra construir com array de C build(vector(bg, en)); } - // ai = max(ai, mi) em [l, r] - void update(int n, int esq, int dir, int l, int r, int mi) { - push(n, esq, dir); - if (esq > r || dir < l || mi <= t[n].m1) return; - if (l <= esq && dir <= r && mi < t[n].m2) { - t[n].lazy = mi; - push(n, esq, dir); - } else { - int mid = (esq + dir) / 2; - update(lc(n), esq, mid, l, r, mi); - update(rc(n), mid + 1, dir, l, r, mi); - t[n].merge(t[lc(n)], t[rc(n)]); + inline int lc(int p) { return 2 * p; } + inline int rc(int p) { return 2 * p + 1; } + node build(int p, int l, int r, const vector &a) { + if (l == r) return t[p] = node(a[l]); + int mid = (l + r) >> 1; + return t[p] = build(lc(p), l, mid, a) + build(rc(p), mid + 1, r, a); + } + void pushsum(int p, int l, int r, ll x) { + t[p].sum += (r - l + 1) * x; + t[p].mi += x; + t[p].mx += x; + t[p].lazy += x; + if (t[p].smi != INF) t[p].smi += x; + if (t[p].smx != -INF) t[p].smx += x; + } + void pushmax(int p, ll x) { + if (x <= t[p].mi) return; + t[p].sum += t[p].fmi * (x - t[p].mi); + if (t[p].mx == t[p].mi) t[p].mx = x; + if (t[p].smx == t[p].mi) t[p].smx = x; + t[p].mi = x; + } + void pushmin(int p, ll x) { + if (x >= t[p].mx) return; + t[p].sum += t[p].fmx * (x - t[p].mx); + if (t[p].mi == t[p].mx) t[p].mi = x; + if (t[p].smi == t[p].mx) t[p].smi = x; + t[p].mx = x; + } + void pushdown(int p, int l, int r) { + if (l == r) return; + int mid = (l + r) >> 1; + pushsum(lc(p), l, mid, t[p].lazy); + pushsum(rc(p), mid + 1, r, t[p].lazy); + t[p].lazy = 0; + + pushmax(lc(p), t[p].mi); + pushmax(rc(p), t[p].mi); + + pushmin(lc(p), t[p].mx); + pushmin(rc(p), t[p].mx); + } + node updatemin(int p, int l, int r, int L, int R, ll x) { + if (l > R || r < L || x >= t[p].mx) return t[p]; + if (l >= L && r <= R && x > t[p].smx) { + pushmin(p, x); + return t[p]; + } + pushdown(p, l, r); + int mid = (l + r) >> 1; + t[p] = updatemin(lc(p), l, mid, L, R, x) + updatemin(rc(p), mid + 1, r, L, R, x); + return t[p]; + } + node updatemax(int p, int l, int r, int L, int R, ll x) { + if (l > R || r < L || x <= t[p].mi) return t[p]; + if (l >= L && r <= R && x < t[p].smi) { + pushmax(p, x); + return t[p]; + } + pushdown(p, l, r); + int mid = (l + r) >> 1; + t[p] = updatemax(lc(p), l, mid, L, R, x) + updatemax(rc(p), mid + 1, r, L, R, x); + return t[p]; + } + node updatesum(int p, int l, int r, int L, int R, ll x) { + if (l > R || r < L) return t[p]; + if (l >= L && r <= R) { + pushsum(p, l, r, x); + return t[p]; } + pushdown(p, l, r); + int mid = (l + r) >> 1; + return t[p] = updatesum(lc(p), l, mid, L, R, x) + + updatesum(rc(p), mid + 1, r, L, R, x); } - void update(int l, int r, int mi) { update(0, 0, n - 1, l, r, mi); } - // soma de [l, r] - ll query(int n, int esq, int dir, int l, int r) { - push(n, esq, dir); - if (esq > r || dir < l) return 0; - if (l <= esq && dir <= r) return t[n].soma; - int mid = (esq + dir) / 2; - return query(lc(n), esq, mid, l, r) + query(rc(n), mid + 1, dir, l, r); + node query(int p, int l, int r, int L, int R) { + if (l > R || r < L) return node(); + if (l >= L && r <= R) return t[p]; + pushdown(p, l, r); + int mid = (l + r) >> 1; + return query(lc(p), l, mid, L, R) + query(rc(p), mid + 1, r, L, R); } - ll query(int l, int r) { return query(0, 0, n - 1, l, r); } + ll query(int l, int r) { return query(1, 0, n - 1, l, r).sum; } + void updatemax(int l, int r, ll x) { updatemax(1, 0, n - 1, l, r, x); } + void updatemin(int l, int r, ll x) { updatemin(1, 0, n - 1, l, r, x); } + void updatesum(int l, int r, ll x) { updatesum(1, 0, n - 1, l, r, x); } } seg; From ff952ca530836ee8fddc5bccd68bf28deb46f507 Mon Sep 17 00:00:00 2001 From: emoreira Date: Wed, 28 Aug 2024 22:42:43 -0300 Subject: [PATCH 2/4] codigo subset convolution e mudancas pequenas nas outras convolucoes --- .../Subset-Convolution/README.md" | 5 +++ .../subset_convolution.cpp" | 39 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 "Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/README.md" create mode 100644 "Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/subset_convolution.cpp" diff --git "a/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/README.md" "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/README.md" new file mode 100644 index 00000000..6356772a --- /dev/null +++ "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/README.md" @@ -0,0 +1,5 @@ +# [Subset Convolution](subset_convolution.cpp) + +Calcula o vetor $C$ a partir de $A$ e $B$ tal que $C[i] = \sum_{\substack{(j \| k) = i}, \substack{(j \land k) = 0}} A[j] \cdot B[k]$ em $\mathcal{O}(N \cdot \log^2 N)$ + +Obs: $\land$ representa o bitwise and e $\|$ representa o bitwise or. diff --git "a/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/subset_convolution.cpp" "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/subset_convolution.cpp" new file mode 100644 index 00000000..9bc36701 --- /dev/null +++ "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/Subset-Convolution/subset_convolution.cpp" @@ -0,0 +1,39 @@ +vector subset_convolution(vector A, vector B) { + int n = int(max(A.size(), B.size())); + int N = 0; + while ((1 << N) < n) N++; + A.resize(1 << N), B.resize(1 << N); + vector a(1 << N, vector(N + 1)), b(1 << N, vector(N + 1)); + for (int i = 0; i < 1 << N; i++) { + int popcnt = __builtin_popcount(i); + a[i][popcnt] = A[i]; + b[i][popcnt] = B[i]; + } + for (int j = 0; j < N; j++) { + for (int i = 0; i < 1 << N; i++) { + if (~i >> j & 1) continue; + for (int popcnt = 0; popcnt <= N; popcnt++) { + a[i][popcnt] += a[i ^ (1 << j)][popcnt]; + b[i][popcnt] += b[i ^ (1 << j)][popcnt]; + } + } + } + vector c(1 << N, vector(N + 1)); + for (int i = 0; i < 1 << N; i++) { + for (int j = 0; j <= N; j++) + for (int k = 0; k + j <= N; k++) c[i][j + k] += a[i][j] * b[i][k]; + } + for (int j = N - 1; j >= 0; j--) { + for (int i = (1 << N) - 1; i >= 0; i--) { + if (~i >> j & 1) continue; + for (int popcnt = 0; popcnt <= N; popcnt++) + c[i][popcnt] -= c[i ^ (1 << j)][popcnt]; + } + } + vector ans(1 << N); + for (int i = 0; i < 1 << N; i++) { + int popcnt = __builtin_popcount(i); + ans[i] = c[i][popcnt]; + } + return ans; +} From 32d7e1c1189b095534554df1a2f2c1f44c06a395 Mon Sep 17 00:00:00 2001 From: emoreira Date: Thu, 29 Aug 2024 16:18:35 -0300 Subject: [PATCH 3/4] tirando a bomba da seg dessa branch --- .../Segment-Tree/Segment-Tree-Beats/README.md | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md diff --git a/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md b/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md deleted file mode 100644 index 486ae4f2..00000000 --- a/Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# [Segment Tree Beats](seg_tree_beats.cpp) - -Segment Tree que suporta update de maximo, update de minimo, update de soma, e query de soma. A construção é $\mathcal{O}(n)$ e as operações de consulta e update são $\mathcal{O}(\log^2 n)$. -**Obs**: Se não usar o update de soma, a complexidade é das operações é $\mathcal{O}(\log n)$ From e03bce100cb49a665c20abbe328de17a26af1644 Mon Sep 17 00:00:00 2001 From: emoreira Date: Thu, 29 Aug 2024 16:31:38 -0300 Subject: [PATCH 4/4] nao sei oq vai acontecer aqui --- .../AND-Convolution/and_convolution.cpp" | 4 ++-- .../OR-Convolution/or_convolution.cpp" | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git "a/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/AND-Convolution/and_convolution.cpp" "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/AND-Convolution/and_convolution.cpp" index 90635f08..9af432f8 100644 --- "a/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/AND-Convolution/and_convolution.cpp" +++ "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/AND-Convolution/and_convolution.cpp" @@ -1,7 +1,7 @@ vector and_convolution(vector A, vector B) { int n = (int)max(A.size(), B.size()); - int N = 0, two = 1; - while (two < n) two <<= 1, N++; + int N = 0; + while ((1 << N) < n) N++; A.resize(1 << N); B.resize(1 << N); vector C(1 << N); diff --git "a/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/OR-Convolution/or_convolution.cpp" "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/OR-Convolution/or_convolution.cpp" index aa45c336..d0dcf2f1 100644 --- "a/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/OR-Convolution/or_convolution.cpp" +++ "b/Codigos/Matem\303\241tica/Convolu\303\247\303\243o/OR-Convolution/or_convolution.cpp" @@ -1,7 +1,7 @@ vector or_convolution(vector A, vector B) { int n = (int)max(A.size(), B.size()); - int N = 0, two = 1; - while (two < n) two <<= 1, N++; + int N = 0; + while ((1 << N) < n) N++; A.resize(1 << N); B.resize(1 << N); vector C(1 << N);