-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #73 from BRUTEUdesc/joao
segtrees melhoradas
- Loading branch information
Showing
31 changed files
with
512 additions
and
279 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
Codigos/Estruturas-de-Dados/Fenwick-Tree/Fenwick/fenwick_tree.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# [Operation Queue](op_queue.cpp) | ||
|
||
Fila que armazena o resultado do operatório dos itens (ou seja, dado uma fila, responde qual é o elemento mínimo, por exemplo). É uma extensão da $std::queue$, permitindo todos os métodos já presentes nela, com a diferença de que $push$ e $pop$ agora são $add$ e $remove$, respectivamente, ambos continuam $\mathcal{O}(1)$ amortizado. A fila agora também permite a operação $get$ que retorna o resultado do operatório dos itens da fila em $\mathcal{O}(1)$ amortizado. Chamar o método $get$ em uma fila vazia é indefinido. | ||
Fila que armazena o resultado do operatório dos itens (ou seja, dado uma fila, responde qual é o elemento mínimo, por exemplo). É uma extensão da `std::queue`, permitindo todos os métodos já presentes nela, com a diferença de que `push` e `pop` agora são `add` e `remove`, respectivamente, ambos continuam $\mathcal{O}(1)$ amortizado. A fila agora também permite a operação `get` que retorna o resultado do operatório dos itens da fila em $\mathcal{O}(1)$ amortizado. Chamar o método `get` em uma fila vazia é indefinido. | ||
|
||
**Obs**: usa a estrutura Operation Stack. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
# [Operation Stack](op_stack.cpp) | ||
|
||
Pilha que armazena o resultado do operatório dos itens (ou seja, dado uma pilha, responde qual é o elemento mínimo, por exemplo). É uma extensão da $std::stack$, permitindo todos os métodos já presentes nela, com a diferença de que $push$ e $pop$ agora são $add$ e $remove$, respectivamente, ambos continuam $\mathcal{O}(1)$ amortizado. A pilha agora também permite a operação $get$ que retorna o resultado do operatório dos itens da pilha em $\mathcal{O}(1)$ amortizado. Chamar o método $get$ em uma pilha vazia é indefinido. | ||
Pilha que armazena o resultado do operatório dos itens (ou seja, dado uma pilha, responde qual é o elemento mínimo, por exemplo). É uma extensão da `std::stack`, permitindo todos os métodos já presentes nela, com a diferença de que `push` e `pop` agora são `add` e `remove`, respectivamente, ambos continuam $\mathcal{O}(1)$ amortizado. A pilha agora também permite a operação `get` que retorna o resultado do operatório dos itens da pilha em $\mathcal{O}(1)$ amortizado. Chamar o método `get` em uma pilha vazia é indefinido. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 2 additions & 7 deletions
9
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-2D/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,3 @@ | ||
# [Seg Tree 2D](seg_tree.cpp) | ||
# [Segment Tree 2D](seg_tree.cpp) | ||
|
||
Segment Tree em 2 dimensões. | ||
|
||
- Complexidade de tempo (Pré-processamento): $\mathcal{O}(N \cdot M)$ | ||
- Complexidade de tempo (Consulta em intervalo): $\mathcal{O}(\log N \cdot \log M)$ | ||
- Complexidade de tempo (Update em ponto): $\mathcal{O}(\log N \cdot \log M)$ | ||
- Complexidade de espaço: $4 * N \cdot 4 * M = \mathcal{O}(N \cdot M)$ | ||
Segment Tree em 2 dimensões, suporta operações de update pontual e consulta em intervalo. A construção é $\mathcal{O}(n \cdot m)$ e as operações de consulta e update são $\mathcal{O}(log(n) \cdot log(m))$. |
11 changes: 2 additions & 9 deletions
11
...struturas-de-Dados/Segment-Tree/Segment-Tree-Beats-Max-And-Sum-Update/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,3 @@ | ||
# [Seg Tree Beats Max and Sum update](seg_tree_beats_max_and_sum_update.cpp) | ||
# [Segment Tree Beats 2](seg_tree_beats_max_and_sum_update.cpp) | ||
|
||
Seg Tree que suporta update de maximo, update de soma e query de soma. | ||
Utiliza uma fila de lazy para diferenciar os updates | ||
|
||
- Complexidade de tempo (Pré-processamento): $\mathcal{O}(N)$ | ||
- Complexidade de tempo (Consulta em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de tempo (Update em ponto): $\mathcal{O}(log(N))$ | ||
- Complexidade de tempo (Update em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de espaço: 2 * 4 * N = $\mathcal{O}(N)$ | ||
Segment Tree que suporta update de maximo, update de soma e query de soma. Utiliza uma fila de lazy para diferenciar os updates. A construção é $\mathcal{O}(n)$ e as operações de consulta e update são $\mathcal{O}(log(n))$. |
9 changes: 2 additions & 7 deletions
9
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Beats-Max-Update/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,3 @@ | ||
# [Seg Tree Beats](seg_tree_beats.cpp) | ||
Seg Tree que suporta update de maximo e query de soma | ||
# [Segment Tree Beats](seg_tree_beats.cpp) | ||
|
||
- Complexidade de tempo (Pré-processamento): $\mathcal{O}(N)$ | ||
- Complexidade de tempo (Consulta em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de tempo (Update em ponto): $\mathcal{O}(log(N))$ | ||
- Complexidade de tempo (Update em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de espaço: $2 * 4 * N = \mathcal{O}(N)$ | ||
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))$. |
10 changes: 2 additions & 8 deletions
10
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Esparsa/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,3 @@ | ||
# [Sparse Seg Tree](seg_tree_sparse.cpp) | ||
# [Segment Tree Esparsa](seg_tree_sparse.cpp) | ||
|
||
Seg Tree Esparsa, ou seja, uma seg tree que não guarda todos os nós, mas apenas os nós que são necessários para responder as queries, permitindo fazer queries em intervalos de tamanho arbitrário. | ||
|
||
Seja $LEN$ o tamanho do intervalo em que a Seg Tree foi construída: | ||
|
||
- Complexidade de tempo (Pré-processamento): $\mathcal{O}(1)$ | ||
- Complexidade de tempo (Consulta em intervalo): $\mathcal{O}(log(LEN))$ | ||
- Complexidade de tempo (Update em ponto): $\mathcal{O}(log(LEN))$ | ||
Segment Tree Esparsa, ou seja, não armazena todos os nós da árvore, apenas os necessários, dessa forma ela suporta operações em intervalos arbitrários. A construção é $\mathcal{O}(1)$ e as operações de consulta e update são $\mathcal{O}(log(L))$, onde $L$ é o tamanho do intervalo. A implementação suporta operações de consulta em intervalo e update pontual. Está implementada para soma, mas pode ser facilmente modificada para outras operações. |
83 changes: 51 additions & 32 deletions
83
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Esparsa/seg_tree_sparse.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,63 @@ | ||
const int SEGMAX = 8e6 + 5; // should be Q * log(DIR-ESQ+1) | ||
const ll ESQ = 0, DIR = 1e9 + 7; | ||
template <ll MINL = ll(-1e9 - 5), ll MAXR = ll(1e9 + 5)> struct SegTree { | ||
const ll neutral = 0; | ||
struct node { | ||
ll val; | ||
int L, R; | ||
node(ll v) : val(v), L(-1), R(-1) { } | ||
}; | ||
ll merge(ll a, ll b) { return a + b; } | ||
|
||
struct seg { | ||
ll tree[SEGMAX]; | ||
int R[SEGMAX], L[SEGMAX], | ||
ptr = 2; // 0 is NULL; 1 is First Root | ||
ll op(ll a, ll b) { return (a + b) % MOD; } | ||
int le(int i) { | ||
if (L[i] == 0) { | ||
L[i] = ptr++; | ||
vector<node> t; | ||
|
||
int newnode() { | ||
t.push_back(node(neutral)); | ||
return int(t.size() - 1); | ||
} | ||
|
||
SegTree() { newnode(); } | ||
|
||
int le(int u) { | ||
if (t[u].L == -1) { | ||
t[u].L = newnode(); | ||
} | ||
return L[i]; | ||
return t[u].L; | ||
} | ||
int ri(int i) { | ||
if (R[i] == 0) { | ||
R[i] = ptr++; | ||
|
||
int ri(int u) { | ||
if (t[u].R == -1) { | ||
t[u].R = newnode(); | ||
} | ||
return R[i]; | ||
return t[u].R; | ||
} | ||
ll query(ll l, ll r, int n = 1, ll esq = ESQ, ll dir = DIR) { | ||
if (r < esq || dir < l) { | ||
return 0; | ||
|
||
ll query(int u, ll l, ll r, ll L, ll R) { | ||
if (l > R || r < L) { | ||
return neutral; | ||
} | ||
if (l <= esq && dir <= r) { | ||
return tree[n]; | ||
if (l >= L && r <= R) { | ||
return t[u].val; | ||
} | ||
ll mid = (esq + dir) / 2; | ||
return op(query(l, r, le(n), esq, mid), query(l, r, ri(n), mid + 1, dir)); | ||
ll mid = l + (r - l) / 2; | ||
ll ql = query(le(u), l, mid, L, R); | ||
ll qr = query(ri(u), mid + 1, r, L, R); | ||
return merge(ql, qr); | ||
} | ||
void update(ll x, ll v, int n = 1, ll esq = ESQ, ll dir = DIR) { | ||
if (esq == dir) { | ||
tree[n] = (tree[n] + v) % MOD; | ||
ll query(ll l, ll r) { return query(0, MINL, MAXR, l, r); } | ||
|
||
void update(int u, ll l, ll r, ll i, ll x) { | ||
debug(u, l, r); | ||
if (l == r) { | ||
t[u].val += x; // soma | ||
// t[u].val = x; // substitui | ||
return; | ||
} | ||
ll mid = l + (r - l) / 2; | ||
if (i <= mid) { | ||
update(le(u), l, mid, i, x); | ||
} else { | ||
ll mid = (esq + dir) / 2; | ||
if (x <= mid) { | ||
update(x, v, le(n), esq, mid); | ||
} else { | ||
update(x, v, ri(n), mid + 1, dir); | ||
} | ||
tree[n] = op(tree[le(n)], tree[ri(n)]); | ||
update(ri(u), mid + 1, r, i, x); | ||
} | ||
t[u].val = merge(t[le(u)].val, t[ri(u)].val); | ||
} | ||
void update(ll i, ll x) { update(0, MINL, MAXR, i, x); } | ||
}; |
9 changes: 4 additions & 5 deletions
9
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Kadani/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,7 @@ | ||
# [Seg Tree Kadani](seg_tree_kadani.cpp) | ||
|
||
Implementação de uma Seg Tree que suporta update de soma e query de soma máxima em intervalo. | ||
Implementação de uma Segment Tree que suporta update de soma em intervalo e query de soma máxima de um subarray em um intervalo. A construção é $\mathcal{O}(n)$ e as operações de consulta e update são $\mathcal{O}(log(n))$. | ||
|
||
- Complexidade de tempo (Pré-processamento): $\mathcal{O}(N)$ | ||
- Complexidade de tempo (Consulta em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de tempo (Update em ponto): $\mathcal{O}(log(N))$ | ||
- Complexidade de espaço: $4 * N = \mathcal{O}(N)$ | ||
É uma Seg Tree normal, a magia está na função `merge` que é a função que combina as respostas dos filhos para computar a resposta do nodo atual. A ideia do `merge` de combinar respostas e informações já computadas dos filhos é muito útil e pode ser aplicada em muitos problemas. | ||
|
||
**Obs**: não considera o subarray vazio como resposta. |
104 changes: 59 additions & 45 deletions
104
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Kadani/seg_tree_kadani.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,76 @@ | ||
namespace seg { | ||
const int MAX = 1e5 + 5; | ||
struct SegTree { | ||
struct node { | ||
ll pref, suff, sum, best; | ||
ll sum, pref, suf, ans; | ||
}; | ||
node new_node(ll v) { return node{v, v, v, v}; } | ||
const node NEUTRAL = {0, 0, 0, 0}; | ||
node tree[4 * MAX]; | ||
node merge(node a, node b) { | ||
ll pref = max(a.pref, a.sum + b.pref); | ||
ll suff = max(b.suff, b.sum + a.suff); | ||
ll sum = a.sum + b.sum; | ||
ll best = max(a.suff + b.pref, max(a.best, b.best)); | ||
return node{pref, suff, sum, best}; | ||
const node neutral = {0, 0, 0, 0}; | ||
node merge(const node &a, const node &b) { | ||
return {a.sum + b.sum, | ||
max(a.pref, a.sum + b.pref), | ||
max(b.suf, b.sum + a.suf), | ||
max({a.ans, b.ans, a.suf + b.pref})}; | ||
} | ||
|
||
int n; | ||
int le(int n) { return 2 * n + 1; } | ||
int ri(int n) { return 2 * n + 2; } | ||
void build(int n, int esq, int dir, const vector<ll> &v) { | ||
if (esq == dir) { | ||
tree[n] = new_node(v[esq]); | ||
vector<node> t; | ||
|
||
void build(int u, int l, int r, const vector<ll> &v) { | ||
if (l == r) { | ||
t[u] = {v[l], v[l], v[l], v[l]}; | ||
} else { | ||
int mid = (esq + dir) / 2; | ||
build(le(n), esq, mid, v); | ||
build(ri(n), mid + 1, dir, v); | ||
tree[n] = merge(tree[le(n)], tree[ri(n)]); | ||
int mid = (l + r) >> 1; | ||
build(u << 1, l, mid, v); | ||
build(u << 1 | 1, mid + 1, r, v); | ||
t[u] = merge(t[u << 1], t[u << 1 | 1]); | ||
} | ||
} | ||
void build(const vector<ll> &v) { | ||
n = v.size(); | ||
build(0, 0, n - 1, v); | ||
|
||
void build(int _n) { // pra construir com tamanho, mas vazia | ||
n = _n; | ||
t.assign(n << 2, neutral); | ||
} | ||
node query(int n, int esq, int dir, int l, int r) { | ||
if (esq > r || dir < l) { | ||
return NEUTRAL; | ||
} | ||
if (l <= esq && dir <= r) { | ||
return tree[n]; | ||
|
||
void build(ll *bg, ll *en) { // pra construir com array estatico | ||
n = int(en - bg); | ||
t.assign(n << 2, neutral); | ||
vector<ll> aux(n); | ||
for (int i = 0; i < n; i++) { | ||
aux[i] = bg[i]; | ||
} | ||
int mid = (esq + dir) / 2; | ||
return merge(query(le(n), esq, mid, l, r), query(ri(n), mid + 1, dir, l, r)); | ||
build(1, 0, n - 1, aux); | ||
} | ||
|
||
void build(const vector<ll> &v) { // pra construir com vector | ||
n = int(v.size()); | ||
t.assign(n << 2, neutral); | ||
build(1, 0, n - 1, v); | ||
} | ||
ll query(int l, int r) { return query(0, 0, n - 1, l, r).best; } | ||
void update(int n, int esq, int dir, int x, ll v) { | ||
if (esq > x || dir < x) { | ||
return; | ||
|
||
node query(int u, int l, int r, int L, int R) { | ||
if (l > R || r < L) { | ||
return neutral; | ||
} | ||
if (l >= L && r <= R) { | ||
return t[u]; | ||
} | ||
if (esq == dir) { | ||
tree[n] = new_node(v); | ||
int mid = (l + r) >> 1; | ||
node ql = query(u << 1, l, mid, L, R); | ||
node qr = query(u << 1 | 1, mid + 1, r, L, R); | ||
return merge(ql, qr); | ||
} | ||
ll query(int l, int r) { return query(1, 0, n - 1, l, r).ans; } | ||
|
||
void update(int u, int l, int r, int i, ll x) { | ||
if (l == r) { | ||
t[u] = {x, x, x, x}; | ||
} else { | ||
int mid = (esq + dir) / 2; | ||
if (x <= mid) { | ||
update(le(n), esq, mid, x, v); | ||
int mid = (l + r) >> 1; | ||
if (i <= mid) { | ||
update(u << 1, l, mid, i, x); | ||
} else { | ||
update(ri(n), mid + 1, dir, x, v); | ||
update(u << 1 | 1, mid + 1, r, i, x); | ||
} | ||
tree[n] = merge(tree[le(n)], tree[ri(n)]); | ||
t[u] = merge(t[u << 1], t[u << 1 | 1]); | ||
} | ||
} | ||
void update(int x, ll v) { update(0, 0, n - 1, x, v); } | ||
} | ||
void update(int i, ll x) { update(1, 0, n - 1, i, x); } | ||
}; |
9 changes: 2 additions & 7 deletions
9
Codigos/Estruturas-de-Dados/Segment-Tree/Segment-Tree-Lazy/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,3 @@ | ||
# [Seg Tree Lazy](seg_tree_lazy.cpp) | ||
# [Segment Tree Lazy](seg_tree_lazy.cpp) | ||
|
||
Implementação padrão de Seg Tree com lazy update | ||
|
||
- Complexidade de tempo (Pré-processamento): $\mathcal{O}(N)$ | ||
- Complexidade de tempo (Consulta em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de tempo (Update em intervalo): $\mathcal{O}(log(N))$ | ||
- Complexidade de espaço: $2 * 4 * N = \mathcal{O}(N)$ | ||
Implementação de uma Segment Tree com Lazy Propagation. Suporta operações de consulta em intervalo e update em intervalo, está implementada para responder consultas de soma e updates de soma em intervalo, ou atribuição em intervalo. A construção é $\mathcal{O}(n)$ e as operações de consulta e update são $\mathcal{O}(log(n))$. |
Oops, something went wrong.