Skip to main content

Sparse_Table

BOJ 35288 Designant.

·473 words·3 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/35288 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๋ฌธ์ œ๋ฅผ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ํŠธ๋ฆฌ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๊ฐ„์„ ์„ $K$๊ฐœ ์ง€์›Œ์„œ ํฌ๋ ˆ์ŠคํŠธ๋กœ ๋งŒ๋“ ๋‹ค. ํฌ๋ ˆ์ŠคํŠธ๋ฅผ ์ž˜ ํ•ฉ์ณ์„œ ํŠธ๋ฆฌ์˜ ์ง€๋ฆ„์ด ์ตœ์†Œ๊ฐ€ ๋˜๋„๋ก ํ•˜์ž. ํฌ๋ ˆ์ŠคํŠธ๋ฅผ ์ž˜ ํ•ฉ์น˜๋Š” ๋ฌธ์ œ๋Š” ๋นŒ๋ผ๋ด‰์œผ๋กœ ์œ ๋ช…ํ•˜๋‹ค. ์ด ๋ฌธ์ œ์— ๋”ฐ๋ฅด๋ฉด, ์„ธ๊ฐœ ์ด์ƒ์˜ ํŠธ๋ฆฌ๋ฅผ ํ•ฉ์น  ๋•Œ, ๊ฐ€์žฅ ๊ธด ํŠธ๋ฆฌ์˜ ์ง€๋ฆ„ ์„ธ๊ฐœ๋ฅผ $a \geq b \geq c$ ๋ผ๊ณ  ํ•˜๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋Š” $\max(a, \lceil\frac{a}{2}\rceil + \lceil\frac{b}{2}\rceil + 1, \lceil\frac{b}{2}\rceil + \lceil\frac{c}{2}\rceil + 2)$ ๊ฒฐ๊ณผ๋Š” ์œ„์™€ ๊ฐ™๊ณ , ์ด๋Š” ์ƒˆ๋กœ ๋งŒ๋“  ๊ฐ„์„ ์„ $0, 1, 2$๊ฐœ ์ด์šฉํ•˜๋Š” ๊ฒฝ๋กœ์ค‘ ๊ฐ€์žฅ ๊ธด๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ๊ทธ๋ฆฌ๋””ํ•˜๊ฒŒ ๊ฐ€์žฅ ๊ธด ์ง€๋ฆ„์˜ ์ค‘์‹ฌ์— ๋‹ค๋ฅธ ์ค‘์‹ฌ๋“ค์„ ์ด์€ ๋ชจ์–‘์—์„œ ๋‚˜์˜จ ๊ฒฐ๊ณผ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ํŠธ๋ฆฌ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ชผ๊ฐœ์„œ ์ง€๋ฆ„๋งŒ ๋น ๋ฅด๊ฒŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์˜ˆ์ œ 1๋ฒˆ์˜ ํŠธ๋ฆฌ๋ฅผ ETT๋ฅผ ํ•˜๋ฉด์„œ ๊ทธ๋ ค๋ณด์ž. ![[Drawing 2026-02-25 22.49.23.excalidraw.png]] ๊ทธ๋ฆฌ๊ณ  ์„ธ๋ฒˆ์งธ ์ฟผ๋ฆฌ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž. $(1, 2), (3, 6), (4, 5, 7)$์œผ๋กœ ๋‚˜๋‰˜์–ด์•ผ ํ•˜๋Š”๋””… ETT๋กœ ์ƒ๊ฐํ•˜๋ฉด, $(1, 2, (5, (3, 6), 4, 7))$ ๊ฐ™์€ ๋А๋‚Œ์œผ๋กœ ๊ทธ๋ฃน์ง€์–ด์ง€๋Š”๊ฑด๊ฐ€? ์ž˜ ์ฒ˜๋ฆฌ๋œ ๋ถ€๋ถ„๋“ค์€ ์ƒ๊ด€ ์—†๋Š”๋ฐ, $(5, 4, 7)$๊ฐ™์€๋ฐ์„œ ์ง€๋ฆ„์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ•˜๋ฉด ์ข‹์„์ง€ ๊ฐ์ด ์•ˆ์˜จ๋‹ค. ์ผ๋‹จ ์ €๊ฑธ $(5), (4,7)$ ๋‘ ๋ฉ์–ด๋ฆฌ๋ฅผ ํ•ฉ์น˜๋Š” ์—ฐ์‚ฐ์œผ๋กœ ๋ณด์ž. ์˜ค์ผ๋Ÿฌ ํˆฌ์–ด ํ…Œํฌ๋‹‰์„ ์ ์šฉํ•˜๋ฉด ์—ฐ์† ๊ตฌ๊ฐ„์— ์†ํ•˜๋Š” ๋…ธ๋“œ๋“ค์˜ ์ง€๋ฆ„์€ ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋กœ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”๊ฑฐ์ง€? ํŠธ๋ฆฌ ๋‘๊ฐœ์˜ ์ง€๋ฆ„์˜ ์–‘๋ ์ ์„ ๊ฐ๊ฐ $(a, b), (c, d)$ ๋ผ๊ณ  ํ• ๋•Œ ๋‘ ํŠธ๋ฆฌ๋ฅผ ํ•ฉ์นœ๊ณณ์—์„œ์˜ ์ง€๋ฆ„์€ $(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)$์ค‘์—์„œ ์กด์žฌํ•œ๋‹ค. ์ด๋ฅผ pull์—ฐ์‚ฐ์œผ๋กœ ์ž˜ ์ •์˜ํ•ด๋ณด์ž. ๊ตฌํ˜„์ด ์ƒ๋‹นํžˆ ์–ด๋ ต๋‹ค.. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ int N, Q; cin >> N >> Q; vector<vector<int>> links(N+1); vector<pii> edges; rep(i, 0, N-1){ int u, v; cin >> u >> v; links[u].push_back(v); links[v].push_back(u); edges.push_back({u, v}); } auto [ETT_in, ETT_out] = ETT(N, links); vector<int> ETT_inv(N+1); rep(i, 1, N+1) ETT_inv[ETT_in[i]] = i; LCA_Tree = new Tree_LCA(N+1, links); vector<Node> nodes(N+1); rep(i, 1, N+1) nodes[i] = Node(ETT_inv[i], ETT_inv[i], 0); SegmentTreeNode seg(N+1, nodes); vector<int> edge_to_subtree(N-1); rep(i, 0, N-1){ auto [u, v] = edges[i]; if(LCA_Tree->depth[u] < LCA_Tree->depth[v]) swap(u, v); edge_to_subtree[i] = u; } while(Q--){ int K; cin >> K; vector<int> cuts(K); rep(i, 0, K) cin >> cuts[i]; vector<Node> Query_nodes; vector<pair<int, bool>> events; // {ETT_idx, is_end} for(auto c: cuts){ int u = edge_to_subtree[c-1]; events.push_back({ETT_in[u], false}); events.push_back({ETT_out[u], true}); } sort(all(events)); int cur = 1; stack<Node> stk; stk.push(Node()); for(auto [idx, is_end]: events){ if(is_end){ Node& top = stk.top(); top = seg.pull(top, seg.query(cur, idx)); cur = idx+1; Query_nodes.push_back(top); stk.pop(); } else{ Node& top = stk.top(); top = seg.pull(top, seg.query(cur, idx-1)); cur = idx; stk.push(Node()); } } Node& top = stk.top(); top = seg.pull(top, seg.query(cur, N)); Query_nodes.push_back(top); sort(all(Query_nodes), [](Node a, Node b){ return a.dist > b.dist; }); int ans = 0; if(Query_nodes.size() > 0) ans = Query_nodes[0].dist; if(Query_nodes.size() > 1) ans = max(ans, (Query_nodes[0].dist+1)/2 + (Query_nodes[1].dist+1)/2 + 1); if(Query_nodes.size() > 2) ans = max(ans, (Query_nodes[1].dist+1)/2 + (Query_nodes[2].dist+1)/2 + 2); cout << ans << "\n"; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 10868 ์ตœ์†Ÿ๊ฐ’

·214 words·2 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/10868 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๊ตฌ๊ฐ„ ์ตœ์†Ÿ๊ฐ’์„ $M$๋ฒˆ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค. ๊ตฌ๊ฐ„ํ•ฉ์€ ๋ˆ„์ ํ•ฉ ๋ฐฐ์—ด์„ ์ด์šฉํ•ด์„œ $O(1)$์— ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ตฌ๊ฐ„ ์ตœ์†Ÿ๊ฐ’์€ ์—ญ์›๊ณผ ์—ญ์—ฐ์‚ฐ์ด ์—†๊ธฐ์—, ๋ˆ„์  ์ตœ์†Ÿ๊ฐ’ ๋ฐฐ์—ด์„ ์ด์šฉํ•˜๊ธฐ ๊ณค๋ž€ํ•˜๋‹ค. ์„ธ๊ทธ๋จผํŠธ ํŠธ๋ฆฌ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌ๊ฐ„ $O(logN)$๊ฐœ์˜ ๊ตฌ๊ฐ„๋งŒ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ’€ ์ˆ˜ ์žˆ๊ฒ ๋‹ค. ํ•˜์ง€๋งŒ, ์—…๋ฐ์ดํŠธ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํฌ์†Œ ๋ฐฐ์—ด์„ ์ด์šฉํ•ด์„œ $O(1)$์— ๊ตฌํ•  ์ˆ˜ ์žˆ์Œ์ด ์•Œ๋ ค์ ธ์žˆ๋‹ค. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): struct RMQ{ // Range Minimum Query int N, H; vector<vector<int>> table; RMQ(int N, vector<int> &arr): N(N){ H = 1; while((1 << H) <= N) H++; table.assign(N, vector<int>(H)); rep(i, 0, N) table[i][0] = arr[i]; rep(j, 1, H) rep(i, 0, N){ int right = i + (1 << (j-1)); if(right < N) table[i][j] = min(table[i][j-1], table[right][j-1]); else table[i][j] = table[i][j-1]; } } int query(int l, int r){ // [L, R] r++; int k = 31 - __builtin_clz(r-l); return min(table[l][k], table[r-(1 << k)][k]); } }; void solve(){ int N, M; N = getu<6, int>(); M = getu<6, int>(); vector<int> A(N); rep(i, 0, N) A[i] = getu<10, int>(); RMQ rmq(N, A); while(M--){ int l, r; l = getu<6, int>(); r = getu<6, int>(); putu<10, int>(rmq.query(l-1, r-1)); } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 17435 ํ•ฉ์„ฑํ•จ์ˆ˜์™€ ์ฟผ๋ฆฌ

·146 words·1 min
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/17435 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ํ•จ์ˆ˜ $f$๊ฐ€ ์ฃผ์–ด์งˆ ๋•Œ, ์ตœ๋Œ€ $500\,000$๋ฒˆ ํ•ฉ์„ฑํ•œ ๊ฐ’์„ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค. ๋‚˜์ด๋ธŒํ•˜๊ฒŒ ๊ณ„์‚ฐํ•˜๋ฉด $O(QN)$์œผ๋กœ ์‹œ๊ฐ„์ดˆ๊ณผ๋‹ค. ์ „์ฒด๋ฅผ ์ „์ฒ˜๋ฆฌํ•ด๋‘๊ธฐ์—”, ๊ณต๊ฐ„๋ณต์žก๋„๊ฐ€ $O(mN)$์œผ๋กœ ๋„ˆ๋ฌด ์ปค์ง„๋‹ค. ๋”ฐ๋ผ์„œ ์ ๋‹นํžˆ ์ „์ฒ˜๋ฆฌ๋ฅผ ํ•ด๋‘์ž. ์ด๋Š” LCA์—์„œ ํ–ˆ๋˜๊ฒƒ๊ณผ ๊ฐ™์ด, ํฌ์†Œ ๋ฐฐ์—ด๋กœ ๊ฐ€๋Šฅํ•  ๊ฒƒ ๊ฐ™๋‹ค. ๊ฐ ์ •์˜์—ญ์— ๋Œ€ํ•ด $1$๋ฒˆ, $2$๋ฒˆ, $4$๋ฒˆ, $\cdots 2^k$๋ฒˆ ํ•ฉ์„ฑํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ž. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ int N; cin >> N; vector<vector<int>> f(20, vector<int>(N+1)); rep(i, 1, N+1) cin >> f[0][i]; rep(k, 1, 20) rep(i, 1, N+1) f[k][i] = f[k-1][f[k-1][i]]; int Q; cin >> Q; while(Q--){ int n, x; cin >> n >> x; rep(k, 0, 20) if(n & (1 << k)) x = f[k][x]; cout << x << "\n"; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 12008 262144

·201 words·1 min
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/12008 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ํ , ๊ฒฐ๊ตญ ๋งˆ์ง€๋ง‰์— ์‚ฌ์šฉํ•œ ๋ชจ๋“  ์ˆซ์ž๋“ค์€ ํ•˜๋‚˜์˜ ๋ฒ”์œ„๋กœ ๋‚˜ํƒ€๋‚  ๊ฒƒ ๊ฐ™๋‹ค. ๋ฒ”์œ„๋ฅผ ์ชผ๊ฐœ๋Š” ๋ง›์˜ DP๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‚˜? $\text{DP}[i][j]$: $i$~$j$๊นŒ์ง€์˜ ์ˆซ์ž๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•ด์„œ ๋งŒ๋“ค์–ด์ง„ ์ˆ˜ ๋ผ๊ณ  ํ•˜๋ฉด $O(N^2)$์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค… ์ด๋Ÿฐ ๋А๋‚Œ์œผ๋กœ $\log$๋กœ ๋ฐ”์šด๋“œ ์‹œํ‚ฌ ์ˆ˜ ์žˆq์„๊นŒ? $(1, 1, 1, 2)$ ์—์„œ 1๋“ค์„ 2๋กœ ๋ฌถ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ฐ ์ธ๋ฑ์Šค์— ๋Œ€ํ•ด์„œ ํ‘œ์‹œ $(2, 1, 2), (1, 2, 2)$ ๋“ฑ์œผ๋กœ ๋‚˜ํƒ€๋‚ด์ ธ์„๋•Œ, 2๋“ค์„ 4๋กœ ๋ฌถ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ํ‘œ์‹œ.. ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ, $(1, 1, 1, 2)$๋Š” 2๋กœ ๋ฌถ์—ˆ์„๋•Œ ๋‹ค์Œ ์ธ๋ฑ์Šค๋Š” $(1, 2, -1, 3)$ ์ฒ˜๋Ÿผ (0-based) ๊ทธ๋Ÿฌ๋ฉด ๋’ค๋กœ ๊ณ„์† ํด์งํด์ง ๋›ฐ์–ด๋‹ค๋‹ˆ๋ฉด์„œ ๊ณ„์‚ฐํ•˜๋ฉด, ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€๊ฐ’์ธ 58์— ๋Œ€ํ•ด $O(N)$๋ฒˆ ํ•˜๋ฉด ๋ ๊ฑฐ๊ฐ™๊ธฐ๋„..? ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ int N; cin >> N; vector<int> A(N); rep(i, 0, N) cin >> A[i]; vector<vector<int>> v(60, vector<int>(N+1, -1)); rep(i, 0, N) v[A[i]][i] = i; int ans = 0; rep(b, 0, 60){ rep(i, 0, N) if(v[b][i] != -1 && v[b][v[b][i]+1] != -1) v[b+1][i] = v[b][v[b][i]+1]; rep(i, 0, N) if(v[b][i] != -1) ans = max(ans, b); } cout << ans; } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 3176 ๋„๋กœ ๋„คํŠธ์›Œํฌ

·146 words·1 min
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/3176 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๋„๋กœ๊ฐ€ N-1๊ฐœ์ธ๊ฑธ ๋ณด๋‹ˆ ํŠธ๋ฆฌ๊ฒ ๊ตฌ๋งŒ ์ด๋•Œ ๊ฒฝ๋กœ์ƒ์—์„œ ๊ฐ€์žฅ ์งง์€ ๋„๋กœ์˜ ๊ธธ์ด์™€ ๊ฐ€์žฅ ๊ธด ๋„๋กœ์˜ ๊ธธ์ด๋ฅผ ์ถœ๋ ฅํ•˜๋ผ๋Š”๋ฐ… HLD๋ฅผ ์จ๋„ ๋˜์ง€๋งŒ, sparse table์—์„œ์˜ RMQ์ฒ˜๋ฆฌ์ฒ˜๋Ÿผ ์ง„ํ–‰ํ•ด๋„ ํฐ ๋ฌธ์ œ๊ฐ€ ์—†๊ฒ ๋‹ค. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ cin >> N; rep(i, 0, N-1){ int u, v, w; cin >> u >> v >> w; links[u].push_back({v, w}); links[v].push_back({u, w}); } dfs(1, -1, 0); rep(j, 1, 20) rep(i, 1, N+1) if(par[i][j-1]){ par[i][j] = par[par[i][j-1]][j-1]; mnDist[i][j] = min(mnDist[i][j-1], mnDist[par[i][j-1]][j-1]); mxDist[i][j] = max(mxDist[i][j-1], mxDist[par[i][j-1]][j-1]); } int Q; cin >> Q; while(Q--){ int u, v; cin >> u >> v; auto [mn, mx] = calc(u, v); cout << mn << ' ' << mx << '\n'; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ

BOJ 1761 ์ •์ ๋“ค์˜ ๊ฑฐ๋ฆฌ

·226 words·2 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/1761 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ํŠธ๋ฆฌ์—์„œ, ๋‘ ์ •์  ์‚ฌ์ด์˜ ๊ฒฝ๋กœ๋Š” ์œ ์ผํ•˜๋‹ค. ํ•ด๋‹น ๊ฒฝ๋กœ๋Š” ๋‘ ์ •์ ์˜ LCA๋ฅผ ์ง€๋‚œ๋‹ค. ๋‘ ์  ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ๋Š” $d(u) + d(v) - 2*d(\text{LCA}(u, v))$๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void dfs(int cur, int _par){ for(auto [nxt, w]: links[cur]){ if(nxt == _par) continue; dist[nxt] = dist[cur] + w; depth[nxt] = depth[cur] + 1; par[nxt][0] = cur; dfs(nxt, cur); } } int LCA(int u, int v){ if(u == v) return u; if(depth[u] < depth[v]) swap(u, v); int diff = depth[u] - depth[v]; rep(i, 0, 16) if((diff >> i) & 1) u = par[u][i]; if(u == v) return u; rrep(i, 16, 0){ if(par[u][i] != par[v][i]){ u = par[u][i]; v = par[v][i]; } } return par[u][0]; } ll getDist(int u, int v){ int lca = LCA(u, v); return dist[u] + dist[v] - 2 * dist[lca]; } void solve(){ cin >> N; rep(i, 0, N-1){ int u, v, w; cin >> u >> v >> w; links[u].push_back({v, w}); links[v].push_back({u, w}); } dfs(1, -1); rep(j, 1, 16) rep(i, 1, N+1) par[i][j] = par[par[i][j-1]][j-1]; cin >> Q; while(Q--){ int u, v; cin >> u >> v; cout << getDist(u, v) << '\n'; } } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ