Enviar pesquisa
Carregar
Heavy-Light Decomposition - Sogang ICPC Team, 2019
•
0 gostou
•
717 visualizações
Suhyun Park
Seguir
Sogang ICPC Team – 2019 여름 고급 스터디
Leia menos
Leia mais
Ciências
Denunciar
Compartilhar
Denunciar
Compartilhar
1 de 29
Baixar agora
Baixar para ler offline
Recomendados
Centroid Decomposition - Sogang ICPC Team, 2019
Centroid Decomposition - Sogang ICPC Team, 2019
Suhyun Park
Persistent Segment Tree - Sogang ICPC Team, 2019
Persistent Segment Tree - Sogang ICPC Team, 2019
Suhyun Park
Fast Fourier Transform - Sogang ICPC Team, 2019
Fast Fourier Transform - Sogang ICPC Team, 2019
Suhyun Park
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Suhyun Park
세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter
세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter
Suhyun Park
퍼시스턴트 세그먼트 트리 - Sogang ICPC Team, 2020 Winter
퍼시스턴트 세그먼트 트리 - Sogang ICPC Team, 2020 Winter
Suhyun Park
정수론적 알고리즘 - Sogang ICPC Team, 2020 Winter
정수론적 알고리즘 - Sogang ICPC Team, 2020 Winter
Suhyun Park
House pricing prediction in R(Regression Project)
House pricing prediction in R(Regression Project)
Adonis Han
Recomendados
Centroid Decomposition - Sogang ICPC Team, 2019
Centroid Decomposition - Sogang ICPC Team, 2019
Suhyun Park
Persistent Segment Tree - Sogang ICPC Team, 2019
Persistent Segment Tree - Sogang ICPC Team, 2019
Suhyun Park
Fast Fourier Transform - Sogang ICPC Team, 2019
Fast Fourier Transform - Sogang ICPC Team, 2019
Suhyun Park
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Suhyun Park
세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter
세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter
Suhyun Park
퍼시스턴트 세그먼트 트리 - Sogang ICPC Team, 2020 Winter
퍼시스턴트 세그먼트 트리 - Sogang ICPC Team, 2020 Winter
Suhyun Park
정수론적 알고리즘 - Sogang ICPC Team, 2020 Winter
정수론적 알고리즘 - Sogang ICPC Team, 2020 Winter
Suhyun Park
House pricing prediction in R(Regression Project)
House pricing prediction in R(Regression Project)
Adonis Han
2012 Dm C3 03
2012 Dm C3 03
chl132435
2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions
현정 김
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
jieun kim
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
JinTaek Seo
해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1
Haesun Park
Boost pp 20091102_서진택
Boost pp 20091102_서진택
JinTaek Seo
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
Kim Hunmin
Python machine learning Ch.4
Python machine learning Ch.4
PartPrime
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
주영 송
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
beom kyun choi
Mais conteúdo relacionado
Mais procurados
2012 Dm C3 03
2012 Dm C3 03
chl132435
2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions
현정 김
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
jieun kim
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
JinTaek Seo
해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1
Haesun Park
Boost pp 20091102_서진택
Boost pp 20091102_서진택
JinTaek Seo
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
Kim Hunmin
Python machine learning Ch.4
Python machine learning Ch.4
PartPrime
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
주영 송
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
beom kyun choi
Mais procurados
(10)
2012 Dm C3 03
2012 Dm C3 03
2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1
Boost pp 20091102_서진택
Boost pp 20091102_서진택
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
Python machine learning Ch.4
Python machine learning Ch.4
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
Heavy-Light Decomposition - Sogang ICPC Team, 2019
1.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 Heavy-Light Decomposition Sogang ICPC
Team – 2019 여름 고급 스터디 Suhyun Park acm.sogang.ac.kr
2.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Heavy-Light Decomposition 트리에다 세그먼트
트리를 얹자!
3.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Heavy-Light Decomposition HLD? ▶ 트리는
선형이 아니다 ▶ 트리를 선형으로 만들어서 세그먼트 트리 같은 걸 같이 쓰고 싶다? ▶ 트리를 선형으로 분해해야!
4.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Heavy-Light Decomposition 18 4 1
5 7 3 1 3 1 4 1 1 1 1 1 1 1 1 아무 노드나 루트로 잡고 서브트리 크기 전처리
5.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Heavy-Light Decomposition 0 1 18 4 1
5 7 3 1 3 1 4 1 1 1 1 1 1 1 1 가장 ‘무거운’ 간선 쪽으로 체인 형성
6.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Heavy-Light Decomposition 0 1 2 3 18 4 1
5 7 3 1 3 1 4 1 1 1 1 1 1 1 1 가장 ‘무거운’ 간선 쪽으로 체인 형성
7.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Heavy-Light Decomposition 0 13 17
8 1 14 12 9 6 2 7 15 16 10 11 3 4 5 18 4 1 5 7 3 1 3 1 4 1 1 1 1 1 1 1 1 모든 체인 형성 (하면서 순서대로 번호 매기기)
8.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Heavy-Light Decomposition 0 1
2 3 8 9 10 13 14 15 4 5 6 7 11 12 16 17 각각의 체인을 선형으로 생각하면 선형 구간 쿼리를 날릴 수 있다
9.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Heavy-Light Decomposition 0 13 17
8 1 14 12 9 6 2 7 15 16 10 11 3 4 5 4–17 → 17, 0–2, 4
10.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Heavy-Light Decomposition 체인을 이루는
간선을 무거운 간선, 아닌 간선을 가벼운 간선으로 생각한다면 ▶ 체인 내부에서의 구간 쿼리는 O (logn) ▶ 임의의 경로 상에서 등장하는 가벼운 간선은 최대 O (logn)개 ▶ 따라서 트리에서의 경로 쿼리가 O ( log2 n ) 이 된다!
11.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Heavy-Light Decomposition ▶ 임의의
경로 상에서 등장하는 가벼운 간선은 최대 O (logn)개 가벼운 간선을 따라 한 칸 내려가면 서브트리의 크기는 반 이상 줄어들기 때문
12.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Heavy-Light Decomposition ▶ 체인과
LCA 테이블 전처리 ▶ 체인마다 세그먼트 트리(혹은 비슷한 구간 쿼리 자료구조) 만들어 주기 ▶ 여러 체인에 걸친 쿼리 구현 말이 쉽지··· 한 번 제대로 짜고 팀노트에 적자 구현은 꽤나 복잡하기 때문에 이후에 언급
13.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 트리와 쿼리 1
BOJ #13510 쿼리 두 종류를 처리해라 ▶ 간선의 비용을 바꿈 ▶ u → v 경로를 이루는 간선들 중에서 가장 큰 비용을 출력
14.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 트리와 쿼리 1
BOJ #13510 1번 정점을 루트라고 하고 DFS 각 정점마다 부모 정점으로 가는 비용을 저장해 두고 HLD
15.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 트리와 쿼리 1
BOJ #13510 source code 91 namespace hld { 92 vector<int> parent, depth, heavy, head, pos, values, segmented_values; 93 int cur_pos; 94 95 int dfs(int v, vector<vector<pii >> const &adj) { 96 int size = 1; 97 int max_c_size = 0; 98 for (auto[c, w] : adj[v]) { 99 if (c == parent[v]) continue; 100 values[c] = w, parent[c] = v, depth[c] = depth[v] + 1; 101 int c_size = dfs(c, adj); 102 size += c_size; 103 if (c_size > max_c_size) 104 max_c_size = c_size, heavy[v] = c; 105 } 106 return size; 107 } source code DFS 돌리면서 서브트리 크기 전처리
16.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 트리와 쿼리 1
BOJ #13510 source code 91 namespace hld { 92 vector<int> parent, depth, heavy, head, pos, values, segmented_values; 93 int cur_pos; 94 95 int dfs(int v, vector<vector<pii >> const &adj) { 96 int size = 1; 97 int max_c_size = 0; 98 for (auto[c, w] : adj[v]) { 99 if (c == parent[v]) continue; 100 values[c] = w, parent[c] = v, depth[c] = depth[v] + 1; 101 int c_size = dfs(c, adj); 102 size += c_size; 103 if (c_size > max_c_size) 104 max_c_size = c_size, heavy[v] = c; 105 } 106 return size; 107 } source code 무거운 간선 여부 전처리 (v → c)
17.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 트리와 쿼리 1
BOJ #13510 source code 109 int decompose(int v, int h, vector<vector<pii >> const &adj) { 110 head[v] = h, pos[v] = cur_pos ++; 111 if (heavy[v] != -1) 112 decompose(heavy[v], h, adj); 113 for (auto[c, w] : adj[v]) { 114 if (c != parent[v] && c != heavy[v]) 115 decompose(c, c, adj); 116 } 117 } source code pos: 새로 붙인 번호, head: 현재 체인의 맨 위의 노드의 번호
18.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 트리와 쿼리 1
BOJ #13510 source code 109 int decompose(int v, int h, vector<vector<pii >> const &adj) { 110 head[v] = h, pos[v] = cur_pos ++; 111 if (heavy[v] != -1) 112 decompose(heavy[v], h, adj); 113 for (auto[c, w] : adj[v]) { 114 if (c != parent[v] && c != heavy[v]) 115 decompose(c, c, adj); 116 } 117 } source code 무거운 간선 먼저 chain 형성
19.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 트리와 쿼리 1
BOJ #13510 source code 109 int decompose(int v, int h, vector<vector<pii >> const &adj) { 110 head[v] = h, pos[v] = cur_pos ++; 111 if (heavy[v] != -1) 112 decompose(heavy[v], h, adj); 113 for (auto[c, w] : adj[v]) { 114 if (c != parent[v] && c != heavy[v]) 115 decompose(c, c, adj); 116 } 117 } source code 가벼운 간선 처리
20.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 119 void init(vector<vector<pii
>> const &adj) { 120 int n = adj.size(); 121 parent = vector<int>(n); 122 depth = vector<int>(n); 123 heavy = vector<int>(n, -1); 124 head = vector<int>(n); 125 pos = vector<int>(n); 126 segmented_values = values = vector<int>(n); 127 cur_pos = 0; 128 129 dfs(0, adj); 130 decompose(0, 0, adj); 131 132 for (int i = 0; i < n; i ++) { 133 segmented_values[pos[i]] = values[i]; 134 } 135 136 segment_tree ::init(segmented_values); 137 } source code
21.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 트리와 쿼리 1
BOJ #13510 139 int query(int a, int b) { 140 int res = 0; 141 for (; head[a] != head[b]; b = parent[head[b]]) { 142 if (depth[head[a]] > depth[head[b]]) 143 swap(a, b); 144 int cur_heavy_path_max = segment_tree ::query(pos[head[b]], pos[b]); 145 res = max(res, cur_heavy_path_max); 146 } 147 if (depth[a] > depth[b]) 148 swap(a, b); 149 if (pos[a] != pos[b]) { 150 int last_heavy_path_max = segment_tree ::query(pos[a] + 1, pos[b]); 151 res = max(res, last_heavy_path_max); 152 } 153 return res; 154 } source code 세그먼트 트리 구현은 생략
22.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 트리와 쿼리 1
BOJ #13510 139 int query(int a, int b) { 140 int res = 0; 141 for (; head[a] != head[b]; b = parent[head[b]]) { 142 if (depth[head[a]] > depth[head[b]]) 143 swap(a, b); 144 int cur_heavy_path_max = segment_tree ::query(pos[head[b]], pos[b]); 145 res = max(res, cur_heavy_path_max); 146 } 147 if (depth[a] > depth[b]) 148 swap(a, b); 149 if (pos[a] != pos[b]) { 150 int last_heavy_path_max = segment_tree ::query(pos[a] + 1, pos[b]); 151 res = max(res, last_heavy_path_max); 152 } 153 return res; 154 } source code chain에서 쿼리 후 a와 b가 같은 체인에 있게 될 때까지 b를 위의 chain으로 올려 줌
23.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 트리와 쿼리 1
BOJ #13510 139 int query(int a, int b) { 140 int res = 0; 141 for (; head[a] != head[b]; b = parent[head[b]]) { 142 if (depth[head[a]] > depth[head[b]]) 143 swap(a, b); 144 int cur_heavy_path_max = segment_tree ::query(pos[head[b]], pos[b]); 145 res = max(res, cur_heavy_path_max); 146 } 147 if (depth[a] > depth[b]) 148 swap(a, b); 149 if (pos[a] != pos[b]) { 150 int last_heavy_path_max = segment_tree ::query(pos[a] + 1, pos[b]); 151 res = max(res, last_heavy_path_max); 152 } 153 return res; 154 } source code 이제 a와 b는 같은 체인에 있으므로 구간 쿼리
24.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 트리와 쿼리 1
BOJ #13510 139 int query(int a, int b) { 140 int res = 0; 141 for (; head[a] != head[b]; b = parent[head[b]]) { 142 if (depth[head[a]] > depth[head[b]]) 143 swap(a, b); 144 int cur_heavy_path_max = segment_tree ::query(pos[head[b]], pos[b]); 145 res = max(res, cur_heavy_path_max); 146 } 147 if (depth[a] > depth[b]) 148 swap(a, b); 149 if (pos[a] != pos[b]) { 150 int last_heavy_path_max = segment_tree ::query(pos[a] + 1, pos[b]); 151 res = max(res, last_heavy_path_max); 152 } 153 return res; 154 } source code 주의: 맨 위의 정점은 포함하면 안 됨!
25.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 트리와 쿼리 1
BOJ #13510 156 int change(int i, int v) { 157 segment_tree ::change(pos[i], v); 158 } source code 원래 정점 번호를 새로 매긴 정점 번호로 고쳐주고 세그먼트 트리 사용
26.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 트리와 쿼리 1
BOJ #13510 163 int main() { 164 cin.tie(nullptr); 165 cout.tie(nullptr); 166 ios_base ::sync_with_stdio(false); 167 168 int n; 169 cin >> n; 170 171 edges.resize(n); 172 vector<vector<pii >> graph(n); 173 174 for (int i = 0; i < n - 1; i ++) { 175 int u, v, w; 176 cin >> u >> v >> w; 177 u --, v --; 178 graph[u].emplace_back(pii(v, w)); 179 graph[v].emplace_back(pii(u, w)); 180 edges[i] = pii(u, v); 181 } source code
27.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 트리와 쿼리 1
BOJ #13510 183 hld ::init(graph); 184 185 int q; 186 cin >> q; 187 while (q --) { 188 int op; 189 cin >> op; source code
28.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 트리와 쿼리 1
BOJ #13510 190 if (op == 1) { 191 int i, c; 192 cin >> i >> c; 193 i --; 194 if (hld ::parent[edges[i].first] == edges[i].second) { 195 hld ::change(edges[i].first, c); 196 } else { 197 hld ::change(edges[i].second, c); 198 } 199 } else { source code
29.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 트리와 쿼리 1
BOJ #13510 199 } else { 200 int u, v; 201 cin >> u >> v; 202 u --, v --; 203 cout << hld ::query(u, v) << 'n'; 204 } 205 } 206 207 return 0; 208 } source code
Baixar agora