-
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.
consertei hld, separei hld em dois arquivos (vértice e aresta), melho…
…rei os updates das segs (#171) * consertei hld, separei em dois arquivos, melhorei os updates das segs * minor fixes * minor fix comentario
- Loading branch information
1 parent
1ec8361
commit 6399c63
Showing
11 changed files
with
193 additions
and
120 deletions.
There are no files selected for viewing
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
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
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 |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# [Heavy-Light Decomposition (em Arestas)](hld_edge.cpp) | ||
|
||
Técnica utilizada para decompor uma árvore em cadeias, e assim realizar operações de caminho e subárvore em $\mathcal{O}(\log N \cdot g(N))$, onde $g(N)$ é a complexidade da operação. Esta implementação suporta queries de soma e update de soma/atribuição, pois usa a estrutura de dados `Segment Tree Lazy` desse almanaque, fazendo assim com que updates e consultas sejam $\mathcal{O}(\log^2 N)$. A estrutura (bem como a operação feita nela) pode ser facilmente trocada, basta alterar o código da `Segment Tree Lazy`, ou ainda, utilizar outra estrutura de dados, como uma `Sparse Table`, caso você tenha queries de mínimo/máximo sem updates, por exemplo. Ao mudar a estrutura, pode ser necessário adaptar os métodos `query` e `update` da HLD. | ||
|
||
A HLD pode ser feita com os valores estando tanto nos vértices quanto nas arestas, essa implementação é feita com os valores nas **arestas**, para ter os valores nos vértices, consulte a implementação de HLD em vértices. | ||
|
||
A construção da HLD é feita em $\mathcal{O}(N + b(N))$, onde $b(N)$ é a complexidade de construir a estrutura de dados utilizada. |
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 |
---|---|---|
@@ -0,0 +1,79 @@ | ||
const int N = 3e5 + 5; | ||
|
||
vector<pair<int, ll>> adj[N]; | ||
|
||
namespace HLD { | ||
int t, sz[N], pos[N], par[N], head[N]; | ||
SegTree seg; // por padrao, a HLD esta codada para usar a SegTree lazy, | ||
// mas pode usar qualquer estrutura de dados aqui | ||
void dfs_sz(int u, int p = -1) { | ||
sz[u] = 1; | ||
for (int i = 0; i < (int)adj[u].size(); i++) { | ||
auto &[v, w] = adj[u][i]; | ||
if (v != p) { | ||
dfs_sz(v, u); | ||
sz[u] += sz[v]; | ||
if (sz[v] > sz[adj[u][0].first] || adj[u][0].first == p) | ||
swap(adj[u][0], adj[u][i]); | ||
} | ||
} | ||
} | ||
void dfs_hld(int u, int p = -1) { | ||
pos[u] = t++; | ||
for (auto [v, w] : adj[u]) { | ||
if (v != p) { | ||
par[v] = u; | ||
head[v] = (v == adj[u][0].first ? head[u] : v); | ||
dfs_hld(v, u); | ||
} | ||
} | ||
} | ||
void build_hld(int u) { | ||
dfs_sz(u); | ||
t = 0, par[u] = u, head[u] = u; | ||
dfs_hld(u); | ||
} | ||
void build(int n, int root) { | ||
build_hld(root); | ||
vector<ll> aux(n, seg.neutral); | ||
for (int u = 0; u < n; u++) { | ||
for (auto [v, w] : adj[u]) | ||
if (u == par[v]) aux[pos[v]] = w; | ||
} | ||
seg.build(aux); | ||
} | ||
ll query(int u, int v) { | ||
if (u == v) return seg.neutral; | ||
if (pos[u] > pos[v]) swap(u, v); | ||
if (head[u] == head[v]) { | ||
return seg.query(pos[u] + 1, pos[v]); | ||
} else { | ||
ll qv = seg.query(pos[head[v]], pos[v]); | ||
ll qu = query(u, par[head[v]]); | ||
return seg.merge(qu, qv); | ||
} | ||
} | ||
ll query_subtree(int u) { | ||
if (sz[u] == 1) return seg.neutral; | ||
return seg.query(pos[u] + 1, pos[u] + sz[u] - 1); | ||
} | ||
// a flag repl diz se o update é de soma ou de replace | ||
void update(int u, int v, ll k, bool repl) { | ||
if (u == v) return; | ||
if (pos[u] > pos[v]) swap(u, v); | ||
if (head[u] == head[v]) { | ||
seg.update(pos[u] + 1, pos[v], k, repl); | ||
} else { | ||
seg.update(pos[head[v]], pos[v], k, repl); | ||
update(u, par[head[v]], k, repl); | ||
} | ||
} | ||
void update_subtree(int u, ll k, bool repl) { | ||
if (sz[u] == 1) return; | ||
seg.update(pos[u] + 1, pos[u] + sz[u] - 1, k, repl); | ||
} | ||
int lca(int u, int v) { | ||
if (pos[u] > pos[v]) swap(u, v); | ||
return head[u] == head[v] ? u : lca(u, par[head[v]]); | ||
} | ||
} |
4 changes: 2 additions & 2 deletions
4
Codigos/Grafos/HLD/README.md → Codigos/Grafos/HLD/HLD-Vértice/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,7 +1,7 @@ | ||
# [Heavy-Light Decomposition](hld.cpp) | ||
# [Heavy-Light Decomposition (em Vértices)](hld.cpp) | ||
|
||
Técnica utilizada para decompor uma árvore em cadeias, e assim realizar operações de caminho e subárvore em $\mathcal{O}(\log N \cdot g(N))$, onde $g(N)$ é a complexidade da operação. Esta implementação suporta queries de soma e update de soma/atribuição, pois usa a estrutura de dados `Segment Tree Lazy` desse almanaque, fazendo assim com que updates e consultas sejam $\mathcal{O}(\log^2 N)$. A estrutura (bem como a operação feita nela) pode ser facilmente trocada, basta alterar o código da `Segment Tree Lazy`, ou ainda, utilizar outra estrutura de dados, como uma `Sparse Table`, caso você tenha queries de mínimo/máximo sem updates, por exemplo. Ao mudar a estrutura, pode ser necessário adaptar os métodos `query` e `update` da HLD. | ||
|
||
A HLD pode ser feita com os valores estando tanto nos nodos quanto nas arestas, consulte os métodos `build` do código para mais detalhes. | ||
A HLD pode ser feita com os valores estando tanto nos vértices quanto nas arestas, essa implementação é feita com os valores nos **vértices**, para ter os valores nas arestas, consulte a implementação de HLD em arestas. | ||
|
||
A construção da HLD é feita em $\mathcal{O}(N + b(N))$, onde $b(N)$ é a complexidade de construir a estrutura de dados utilizada. |
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 |
---|---|---|
@@ -0,0 +1,74 @@ | ||
const int N = 3e5 + 5; | ||
|
||
vector<int> adj[N]; | ||
|
||
namespace HLD { | ||
int t, sz[N], pos[N], par[N], head[N]; | ||
SegTree seg; // por padrao, a HLD esta codada para usar a SegTree lazy, | ||
// mas pode usar qualquer estrutura de dados aqui | ||
void dfs_sz(int u, int p = -1) { | ||
sz[u] = 1; | ||
for (int &v : adj[u]) { | ||
if (v != p) { | ||
dfs_sz(v, u); | ||
sz[u] += sz[v]; | ||
if (sz[v] > sz[adj[u][0]] || adj[u][0] == p) swap(v, adj[u][0]); | ||
} | ||
} | ||
} | ||
void dfs_hld(int u, int p = -1) { | ||
pos[u] = t++; | ||
for (int v : adj[u]) { | ||
if (v != p) { | ||
par[v] = u; | ||
head[v] = (v == adj[u][0] ? head[u] : v); | ||
dfs_hld(v, u); | ||
} | ||
} | ||
} | ||
void build_hld(int u) { | ||
dfs_sz(u); | ||
t = 0, par[u] = u, head[u] = u; | ||
dfs_hld(u); | ||
} | ||
void build(vector<ll> v, int root) { // pra buildar com valores nos nodos | ||
build_hld(root); | ||
vector<ll> aux(v.size()); | ||
for (int i = 0; i < (int)v.size(); i++) aux[pos[i]] = v[i]; | ||
seg.build(aux); | ||
} | ||
void build(int n, int root) { // pra buildar com neutro nos nodos | ||
build(vector<ll>(n, seg.neutral), root); | ||
} | ||
void build(ll *bg, ll *en, int root) { // pra buildar com array de C | ||
build(vector<ll>(bg, en), root); | ||
} | ||
ll query(int u, int v) { | ||
if (pos[u] > pos[v]) swap(u, v); | ||
if (head[u] == head[v]) { | ||
return seg.query(pos[u], pos[v]); | ||
} else { | ||
ll qv = seg.query(pos[head[v]], pos[v]); | ||
ll qu = query(u, par[head[v]]); | ||
return seg.merge(qu, qv); | ||
} | ||
} | ||
ll query_subtree(int u) { return seg.query(pos[u], pos[u] + sz[u] - 1); } | ||
// a flag repl diz se o update é de soma ou de replace | ||
void update(int u, int v, ll k, bool repl) { | ||
if (pos[u] > pos[v]) swap(u, v); | ||
if (head[u] == head[v]) { | ||
seg.update(pos[u], pos[v], k, repl); | ||
} else { | ||
seg.update(pos[head[v]], pos[v], k, repl); | ||
update(u, par[head[v]], k, repl); | ||
} | ||
} | ||
void update_subtree(int u, ll k, bool repl) { | ||
seg.update(pos[u], pos[u] + sz[u] - 1, k, repl); | ||
} | ||
int lca(int u, int v) { | ||
if (pos[u] > pos[v]) swap(u, v); | ||
return head[u] == head[v] ? u : lca(u, par[head[v]]); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.