SlideShare uma empresa Scribd logo
1 de 29
Baixar para ler offline
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
0
Heavy-Light Decomposition
Sogang ICPC Team – 2019 여름 고급 스터디
Suhyun Park
acm.sogang.ac.kr
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
Heavy-Light Decomposition
트리에다 세그먼트 트리를 얹자!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
Heavy-Light Decomposition
HLD?
▶ 트리는 선형이 아니다
▶ 트리를 선형으로 만들어서 세그먼트 트리 같은 걸 같이 쓰고 싶다?
▶ 트리를 선형으로 분해해야!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
Heavy-Light Decomposition
18
4 1 5 7
3 1 3 1 4 1
1 1 1 1 1 1 1
아무 노드나 루트로 잡고 서브트리 크기 전처리
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
Heavy-Light Decomposition
0
1
18
4 1 5 7
3 1 3 1 4 1
1 1 1 1 1 1 1
가장 ‘무거운’ 간선 쪽으로 체인 형성
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
가장 ‘무거운’ 간선 쪽으로 체인 형성
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
모든 체인 형성 (하면서 순서대로 번호 매기기)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
Heavy-Light Decomposition
0 1 2 3
8 9 10
13 14 15
4 5 6
7 11 12
16 17
각각의 체인을 선형으로 생각하면 선형 구간 쿼리를 날릴 수 있다
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
Heavy-Light Decomposition
체인을 이루는 간선을 무거운 간선, 아닌 간선을 가벼운 간선으로
생각한다면
▶ 체인 내부에서의 구간 쿼리는 O (logn)
▶ 임의의 경로 상에서 등장하는 가벼운 간선은 최대 O (logn)개
▶ 따라서 트리에서의 경로 쿼리가 O
(
log2
n
)
이 된다!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
10
Heavy-Light Decomposition
▶ 임의의 경로 상에서 등장하는 가벼운 간선은 최대 O (logn)개
가벼운 간선을 따라 한 칸 내려가면 서브트리의 크기는 반 이상
줄어들기 때문
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
Heavy-Light Decomposition
▶ 체인과 LCA 테이블 전처리
▶ 체인마다 세그먼트 트리(혹은 비슷한 구간 쿼리 자료구조)
만들어 주기
▶ 여러 체인에 걸친 쿼리 구현
말이 쉽지··· 한 번 제대로 짜고 팀노트에 적자
구현은 꽤나 복잡하기 때문에 이후에 언급
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
12
트리와 쿼리 1 BOJ #13510
쿼리 두 종류를 처리해라
▶ 간선의 비용을 바꿈
▶ u → v 경로를 이루는 간선들 중에서 가장 큰 비용을 출력
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
트리와 쿼리 1 BOJ #13510
1번 정점을 루트라고 하고 DFS
각 정점마다 부모 정점으로 가는 비용을 저장해 두고 HLD
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 돌리면서 서브트리 크기 전처리
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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: 현재 체인의 맨 위의 노드의 번호
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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 형성
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
가벼운 간선 처리
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
세그먼트 트리 구현은 생략
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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으로 올려 줌
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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는 같은 체인에 있으므로 구간 쿼리
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
주의: 맨 위의 정점은 포함하면 안 됨!
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24
트리와 쿼리 1 BOJ #13510
156 int change(int i, int v) {
157 segment_tree ::change(pos[i], v);
158 }
source code
원래 정점 번호를 새로 매긴 정점 번호로 고쳐주고 세그먼트 트리 사용
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
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

Mais conteúdo relacionado

Mais procurados

2012 Dm C3 03
2012 Dm C3 032012 Dm C3 03
2012 Dm C3 03chl132435
 
2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions현정 김
 
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522jieun kim
 
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택JinTaek Seo
 
해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1Haesun Park
 
Boost pp 20091102_서진택
Boost pp 20091102_서진택Boost pp 20091102_서진택
Boost pp 20091102_서진택JinTaek Seo
 
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기Kim Hunmin
 
Python machine learning Ch.4
Python machine learning Ch.4Python machine learning Ch.4
Python machine learning Ch.4PartPrime
 
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)주영 송
 
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료beom kyun choi
 

Mais procurados (10)

2012 Dm C3 03
2012 Dm C3 032012 Dm C3 03
2012 Dm C3 03
 
2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions2018 Ajou Programming Contest solutions
2018 Ajou Programming Contest solutions
 
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
집단지성프로그래밍 05. 최적화(optimization.ipynb) 김지은_20150522
 
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
 
해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1해커에게 전해들은 머신러닝 #1
해커에게 전해들은 머신러닝 #1
 
Boost pp 20091102_서진택
Boost pp 20091102_서진택Boost pp 20091102_서진택
Boost pp 20091102_서진택
 
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
 
Python machine learning Ch.4
Python machine learning Ch.4Python machine learning Ch.4
Python machine learning Ch.4
 
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
MapReduce 실행 샘플 (K-mer Counting, K-means Clustering)
 
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
 

Heavy-Light Decomposition - Sogang ICPC Team, 2019