-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathHLD.cpp
More file actions
94 lines (83 loc) · 2.51 KB
/
HLD.cpp
File metadata and controls
94 lines (83 loc) · 2.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <bits/stdc++.h>
#include "../Data Structures/SegTreeLazy.cpp" //LATEX_IGNORED_LINE
#define ll long long
using namespace std;
const bool EDGE = false;
struct HLD {
public:
vector<vector<int>> g;
vector<int> sz, parent, tin, nxt;
SegTree<int> seg;
HLD() : seg(1) {}
HLD(int n) : seg(n) { init(n); }
void init(int n){
t = 0; seg = SegTree<int>(n);
g.resize(n); tin.resize(n);
sz.resize(n);nxt.resize(n);
parent.resize(n);
}
void addEdge(int u, int v){
g[u].emplace_back(v);
g[v].emplace_back(u);
}
void build(int root=0){
nxt[root]=root;
dfs(root, root);
hld(root, root);
}
ll query_path(int u, int v){
if(tin[u] < tin[v]) swap(u, v);
if(nxt[u] == nxt[v]) return qry(tin[v]+EDGE, tin[u]);
return qry(tin[nxt[u]], tin[u]) + query_path(parent[nxt[u]], v);
}
void update_path(int u, int v, ll x){
if(tin[u] < tin[v]) swap(u, v);
if(nxt[u] == nxt[v]) return updt(tin[v]+EDGE, tin[u], x);
updt(tin[nxt[u]], tin[u], x); update_path(parent[nxt[u]], v, x);
}
private:
ll qry(int l, int r){ if(EDGE && l>r) return seg.NEUTRO; return seg.query(l, r); }
void updt(int l, int r, ll x){ if(EDGE && l>r) return; seg.update(l, r, x); }
void dfs(int u, int p){
sz[u] = 1, parent[u] = p;
for(auto &v : g[u]) if(v != p) {
dfs(v, u); sz[u] += sz[v];
if(sz[v] > sz[g[u][0]] || g[u][0] == p)
swap(v, g[u][0]);
}
}
int t=0;
void hld(int u, int p){
tin[u] = t++;
for(auto &v : g[u]) if(v != p)
nxt[v] = (v == g[u][0] ? nxt[u] : v),
hld(v, u);
}
/// OPTIONAL ///
int lca(int u, int v){
while(!inSubtree(nxt[u], v)) u = parent[nxt[u]];
while(!inSubtree(nxt[v], u)) v = parent[nxt[v]];
return tin[u] < tin[v] ? u : v;
}
bool inSubtree(int u, int v){ return tin[u] <= tin[v] && tin[v] < tin[u] + sz[u]; }
//query/update_subtree[tin[u]+EDGE, tin[u]+sz[u]-1];
vector<pair<int, int>> pathToAncestor(int u, int a){
vector<pair<int, int>> ans;
while(nxt[u] != nxt[a])
ans.emplace_back(tin[nxt[u]], tin[u]),
u = parent[nxt[u]];
ans.emplace_back(tin[a], tin[u]);
return ans;
}
};
/*LATEX_DESC_BEGIN***************************
**Heavy-Light Decomposition**
**Complexity:** O(LogN * (qry || updt))
Change qry(l, r) and updt(l, r) to call a query and update structure of your will
HLD hld(n); //call init
hld.add_edges(u, v); //add all edges
hld.build(); //Build everthing for HLD
tin[u] -> Pos in the structure (Seg, Bit, ...)
nxt[u] -> Head/Endpoint
IMPORTANTE! o grafo deve estar 0-indexado!
*****************************LATEX_DESC_END*/