Skip to main content

Greedy

BOJ 26857 Cell Game

·858 words·5 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/26857 λ²ˆμ—­ 문제 λ²ˆμ—­ # 두 ν˜•μ œ Aldo와 Bondan은 COVID-19 팬데믹 상황이 μ•…ν™”λ˜μ–΄ λ„μ‹œκ°€ λ‹€μ‹œ λ΄‰μ‡„λ˜λ©΄μ„œ 집에 κ°‡ν˜€ μžˆμŠ΅λ‹ˆλ‹€. 그듀은 ν•™κΈ°λ₯Ό 마치고 λ°©ν•™ μ€‘μ΄μ§€λ§Œ, μ§‘ λ°–μœΌλ‘œ λ‚˜κ°ˆ 수 μ—†λ‹€λ©΄ 무슨 방학을 즐길 수 μžˆμ„κΉŒμš”? ν•˜μ§€λ§Œ 지루함은 μ°½μ˜μ„±μ„ λΆˆλŸ¬μΌμœΌν‚΅λ‹ˆλ‹€. 그듀은 μ§€λ£¨ν•œ λ°©ν•™ λ™μ•ˆ μƒˆλ‘œμš΄ κ²Œμž„μ„ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.

BOJ 13448 SW μ—­λŸ‰ ν…ŒμŠ€νŠΈ

·233 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/13448 🧐 κ΄€μ°° 및 μ ‘κ·Ό # μ–»λŠ” μ μˆ˜κ°€ $M_i - t * p_i$κ°€ μ•„λ‹Œ $M_i$라면, λ‹¨μˆœν•œ λ°°λ‚­λ¬Έμ œμΌν…λ°.. 이걸 μœ„ν•΄μ„œ $N$에 λŒ€ν•œ λΉ„νŠΈλ§ˆμŠ€ν‚Ήμ„ μΆ”κ°€ν•˜λŠ”κ±΄ λ―ΈμΉœμ§“μ΄λ‹€ 그런데, μ–΄λ–€ λ¬Έμ œλ“€μ„ ν’€κΈ°λ‘œ κ²°μ •ν–ˆλ‹€λ©΄, κ·Έ λ¬Έμ œλ“€μ— λŒ€ν•΄ μˆœμ„œλ₯Ό μ •ν•˜λŠ”κ±΄ κ·Έλ¦¬λ””ν•˜κ²Œ λ˜μ§€ μ•Šλ‚˜? 문제 $i, j$κ°€ μžˆλ‹€κ³  ν•˜μž. $i \rightarrow j$둜 ν’€λ©΄ $(M_i - t * P_i) + (M_j - (t + R_i)*P_j)$ 점을 μ–»κ²Œ 되고 $j -> i$둜 ν’€λ©΄ $(M_j - t*P_j) + (M_i - (t + R_j) * P_i)$ 점을 μ–»κ²Œ λœλ‹€. μœ„μ—μ„œ μ•„λž˜ 식을 λΉΌλ©΄ $P_i * R_j - P_j * R_i$ 이고, $i \rightarrow j$κ°€ 이득이기 μœ„ν•΄μ„  이게 μ–‘μˆ˜μ—¬μ•Όν•˜λ―€λ‘œ $\frac{P_i}{R_i} \geq \frac{P_j}{R_j}$둜 μ •λ ¬ν•˜λŠ” 그리디 μ „λž΅μ΄ μœ νš¨ν•˜λ‹€. κ·Έλ ‡λ‹€λ©΄ 이 μˆœμ„œλ‘œ 냅색 DPλ₯Ό μˆ˜ν–‰ν•˜μž. πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N, T; cin >> N >> T; vector<Problem> Prob(N); rep(i, 0, N) cin >> Prob[i].M; rep(i, 0, N) cin >> Prob[i].P; rep(i, 0, N) cin >> Prob[i].R; sort(all(Prob), [](Problem &A, Problem &B){ return A.P * B.R > B.P * A.R; }); vector<ll> DP(T+1); for(auto [M, P, R]: Prob) rrep(t, 0, T+1){ if(t - R < 0) break; DP[t] = max(DP[t], DP[t - R] + (M - P*t)); } ll ans = 0; rep(i, 0, T+1) ans = max(ans, DP[i]); cout << ans; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 16225 제271회 μ›°λ…Έμš΄μ»΅

·282 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/16225 🧐 κ΄€μ°° 및 μ ‘κ·Ό # μ•½κ°„ κ²Œμž„μ΄λ‘ μ μ΄λ„€. $(A_i, B_i), (A_j, B_j)$ 두가지λ₯Ό κ³ λ₯Έλ‹€. μ΄λ•Œ, $B_i > B_j$라면 $A_j$, $B_i < B_j$라면 $A_i$λ₯Ό μ–»κ²Œλœλ‹€. 직관적인것듀을 μƒκ°ν•΄λ³΄μž. $A_i$κ°€ 크고, $B_i$κ°€ μž‘μ€κ²ƒλ“€μ΄ 있으면 μ’‹κ² λ‹€. μœ„ μΉœκ΅¬λ“€μ„ $A_i$κ°€ μž‘κ±°, $B_i$κ°€ 큰 μΉœκ΅¬λ“€μ΄λž‘ λ§€μΉ­μ‹œμΌœμ„œ 없애버리면 μ’‹λ‹€. $B$κ°€ κ°€μž₯ μž‘μ€ λ¬Έμ œλŠ” μ–Έμ œλ‚˜ λ‚΄κ°€ ν’€κ²Œ λœλ‹€. $B$κ°€ κ°€μž₯ 큰 λ¬Έμ œλŠ” μ–Έμ œλ‚˜ μƒλŒ€κ°€ ν’€κ²Œ λœλ‹€. 이μͺ½μ—μ„œ μΆœλ°œν•΄λ³ΌκΉŒ? $B$에 λŒ€ν•œ μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬ν•΄λ³΄μž. 그러면 버릴 문제λ₯Ό ν•˜λ‚˜ κ³ λ₯Ό 수 μžˆλ‹€. 일단 예제λ₯Ό $B$에 λŒ€ν•œ μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬ν•œ ν›„, $A$만 남기면 $(2, 4, 8, 6)$ 이 λœλ‹€. μ΄λ•Œ 2λ₯Ό νƒν•˜κ³  4λ₯Ό 버렀고, 8을 νƒν•˜κ³  6을 버리면 10이 λœλ‹€. μ—¬λŸ¬κ°œλ‘œ μƒκ°ν•΄λ³΄λ‹ˆ, μ•½κ°„ μ˜¬λ°”λ₯Έ κ΄„ν˜Έ λ¬Έμžμ—΄ λ§›μœΌλ‘œ λ˜λŠ”λ°… 20만 $O(N^3)$ DPλŠ” μ•ˆλœλ‹€μ΄ $\text{DP}[i][j]$: $i$λ²ˆμ§ΈκΉŒμ§€ λ΄€μ„λ•Œ, μ—¬λŠ”κ΄„ν˜Έκ°€ $j$κ°œμΌλ•Œ μ΅œλŒ“κ°’ 이라고 ν•˜λ©΄ $O(N^2)$도 λœλ‹€λ§Œ… 근데 μ—΄λ¦¬λŠ” κ΄„ν˜ΈλŠ”, 생각보닀 λΉ λ₯΄κ²Œ μ—΄μ–΄μ€˜μ•Όν•œλ‹€. 1λ²ˆμ„ λ¨Ήμ—ˆμœΌλ‹ˆ, $(2, 3)$쀑에 ν•˜λ‚˜λŠ” 무쑰건 μ—΄μ–΄μ•Ό ν•œλ‹€. $2$λ₯Ό λ¨Ήμ—ˆλ‹€λ©΄, $3, 4, 5$쀑 ν•˜λ‚˜λŠ” 무쑰건 μ—΄μ–΄μ•Ό ν•œλ‹€. $3$을 λ¨Ήμ—ˆλ‹€λ©΄, $2, 4, 5$쀑 ν•˜λ‚˜λŠ” 무쑰건 λ¨Ήμ–΄μ•Ό ν•œλ‹€. $k$개 λ¨Ήμ—ˆλ‹€λ©΄, $2 \leq i \leq 2*k + 1$ λ²”μœ„ λ‚΄μ—μ„œ ν•œκ°œλ₯Ό 더 λ¨Ήμ–΄μ€˜μ•Όν•œλ‹€. μ΄λ•Œ μ΅œλŒ“κ°’μ„ λ¨Ήμ–΄μ€˜μ•Όν•˜κ³ , 점 μ—…λ°μ΄νŠΈκ°€ μžˆμœΌλ‹ˆ μ„Έκ·Έλ¨ΌνŠΈ 트리둜 λ˜κ² λ‹€. μ„Έκ·Έμ›Œν‚Ή γ„±.γ„± πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N; cin >> N; vector<pii> A(N); rep(i, 0, N) cin >> A[i].first; rep(i, 0, N) cin >> A[i].second; sort(all(A), [](pii a, pii b){ return a.second < b.second; }); vector<ll> v; rep(i, 0, N) v.push_back(A[i].first); ST.init(N); rep(i, 0, N) ST.set(i, v[i]); ST.build(); ll ans = v[0]; rep(i, 1, N/2){ auto [val, idx] = ST.seg_walk(1, i*2); ans += val; ST.update(idx, 0); } cout << ans << '\n'; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 28433 κ²Œλ¦¬λ§¨λ”λ§

·361 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/28433 🧐 κ΄€μ°° 및 μ ‘κ·Ό # μˆ˜μ—΄μ„ μ›ν•˜λŠ” 개수의 μ—°μ†λœ κ΅¬κ°„μœΌλ‘œ λ‚˜λˆ„μ–΄μ„œ κ΅¬κ°„μ˜ 합이 μ–‘μˆ˜μΈ 개수 - κ΅¬κ°„μ˜ 합이 음수인 개수λ₯Ό μ–‘μˆ˜λ‘œ λ§Œλ“€μž. μ§κ΄€μ μœΌλ‘œ μƒκ°ν•΄λ³΄μž. μ§€κΈˆκΉŒμ§€μ˜ 합이 μ–‘μˆ˜λ©΄ -> 걍 μž˜λΌλ²„λ¦¬λŠ”κ²Œ 이득이닀. μ§€κΈˆκΉŒμ§€μ˜ 합이 음수면 -> 이게 μ’€ 고민이넀 λ‹€μŒ λ†ˆμ΄ 음수면 -> 계속 먹으면 λ˜λŠ”λ°, -100 -100 -100 1 -100 같은 κ²½μš°μ—λŠ” ν•œλ²ˆμ— 큰덩이둜 λ¨ΉλŠ”κ²Œ μ΄λ“μΌμˆ˜λ„ μžˆμ§€ μ•Šλ‚˜? 일단 μ–‘μˆ˜/μŒμˆ˜λŠ” λ¬Άμ–΄μ„œ 생각할 수 μžˆμ„κ±°κ°™κ³ , 음수 친ꡬλ₯Ό μ™Όμͺ½/였λ₯Έμͺ½μœΌλ‘œ λ³΄λ‚΄μ„œ μ–‘μˆ˜ 덩어리에 ν•©λ₯˜μ‹œν‚¬μ§€ λ§μ§€λ§Œ κ³ λ―Όν•˜λ©΄ λ˜λŠ”κ²ƒκ°™λ‹€. κ·Έλ ‡λ‹€λ©΄ μ–‘μˆ˜ / μ–‘μˆ˜ / 음수 / μ–‘μˆ˜ / 음수 / μ–‘μˆ˜ μ΄λ ‡κ²Œ 생겼을텐데, μ΄μ œλŠ” 음수인 것이 λ‘κ°œ 이상 λΆ™μ–΄μ„œ λ“±μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€. μ–‘μˆ˜ 개수 > 음수 개수라면 1을 좜λ ₯ν•˜λ©΄ λœλ‹€! μ–‘μˆ˜ 개수 = 음수 개수라면 ν•œ 칸이 κ²°ν•© κ°€λŠ₯ν•œμ§€ μƒκ°ν•˜λ©΄ λœλ‹€! μ–‘μˆ˜ 개수 < 음수 개수라면 두 칸이 κ²°ν•© κ°€λŠ₯ν•œμ§€ μƒκ°ν•˜λ©΄ λœλ‹€! 이게 λ‘λ²ˆ ν™•μΈν•΄μ•Όν•΄μ„œ λ¬Έμ œμ§€λ§Œ, κ²°ν•© κ°€λŠ₯ν•˜λ©΄ 무쑰건 κ²°ν•©ν•œλ‹€λŠ” 방식이 κ·Έλ¦¬λ””ν•˜κ²Œ κ°€λŠ₯ν•˜λ‹€. 직관적이긴 ν•˜λ„€ 라고!!!!!!!! μƒκ°ν–ˆμ§€λ§Œ!!!!!!!!! ν‹€λ Έλ‹€. $[2, -1, -1, 2, -1, -1]$ 의 경우.. $(2, -1), (-1, 2), (-1, -1)$둜 묢으면 λœλ‹€. κ·ΈλŸ¬λ‹ˆκΉŒ λ§˜λŒ€λ‘œ 묢으면 μ•ˆλœλ‹€λŠ”κ±΄λ°…. 그리디 문제 μΆ”μ²œλ°›μ•„μ„œ ν’€λ˜κ±°λΌ μ—¬κΈ°μ„œ DP둜 ν‹€μ§„ μ•Šμ•˜κ³ , μ†”μ§νžˆ ν‰μ†Œκ°™μ•˜μœΌλ©΄ μ„Έκ·ΈDP둜 νŠ€μ—ˆμ„λ“― πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N; cin >> N; vector<ll> v; ll sum = 0; rep(i, 0, N){ ll x; cin >> x; if(x != 0) v.push_back(x); sum += x; } if(v.size() == 0){ cout << "NO\n"; return; } ll cur = 0; int pcnt = 0, ncnt = 0; for(auto x: v){ if(x > 0){ if(cur <= 0 && cur +x > 0) cur += x; else{ if(cur > 0) pcnt++; if(cur < 0) ncnt++; cur = x; } } else{ if(cur > 0 && cur + x <= 0){ if(cur > 0) pcnt++; if(cur < 0) ncnt++; cur = x; } else{ cur += x; } } // cout << "cur: " << cur << " pcnt: " << pcnt << " ncnt: " << ncnt << "\n"; } if(cur > 0) pcnt++; if(cur < 0) ncnt++; cout << (pcnt > ncnt ? "YES" : "NO") << "\n"; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 11920 버블 μ •λ ¬

·208 words·1 min
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/11920 🧐 κ΄€μ°° 및 μ ‘κ·Ό # λ°°μ—΄ $[3, 4, 1, 2, 7, 6]$이 μžˆλ‹€κ³  ν•˜μž. 처음 ν•œλ°”ν€΄λ₯Ό 돌면 μ–΄λ–»κ²Œ λ˜μ§€? $[3, 1, 2, 4, 6, 7]$이 λœλ‹€. 이걸 μ–΄λ–»κ²Œ 해석할 수 μžˆμ„κΉŒ? κ°€μž₯ 큰 μˆ˜λŠ” 맨 였λ₯Έμͺ½μ— κ³ μ •λœλ‹€. λ‹€λ₯Έ μˆ˜λ“€μ€, 였λ₯Έμͺ½μ— λΆ™μ–΄μžˆμˆ˜κ°€ μžκΈ°λ³΄λ‹€ μž‘μ€κ²ƒλ“€μ„ μ™Όμͺ½μœΌλ‘œ λ‹€ λ°€κ³ , 였λ₯Έμͺ½μœΌλ‘œ κ°„λ‹€. 였큰수? μŠ€νƒ? κ·ΈλŸ°λ§›μΈλ° 이거 λ‘λ²ˆν•˜λ©΄ μ–΄λ–»κ²Œ? $[1, 2, 3, 4, 6, 7]$이 λœλ‹€. λ‚˜ 5 μ•ˆμΌμ—ˆκ΅¬λ‚˜ γ…‹γ…‹ 이런 값을 λ‘κ°œμ •λ„ λ“€κ³ μžˆλ‹€κ°€..? λ­”κ°€ κ·ΈλŸ°λŠλ‚Œ…? $K$번 μ§„ν–‰ν•œλ‹€κ³  ν•˜λ©΄, 값을 $K$κ°œμ •λ„ λ“€κ³ μžˆλ‹€κ°€, λ“€κ³ μžˆλŠ” 값쀑 μ € μž‘μ€κ±°λ³΄λ‹€ μž‘μœΌλ©΄ κ·ΈλŒ€λ‘œ ν†΅κ³Όμ‹œν‚€κ³ , 그것보닀 크닀면? μ–΄λ–»κ²Œ λ˜λŠ”κ±°μ§€? $[5, 7, 4, 3, 6, 8, 1, 2]$λ₯Ό ν•΄λ³΄μž. $[5, 4, 3, 6, 7, 1, 2, 8]$ $[4, 3, 5, 6, 1, 2, 7, 8]$ λ‘κ°œ λ“€κ³ μžˆλ‹€κ°€ 큰거 λ§Œλ‚˜λ©΄ μž‘μ€κ°’ λΉΌλ²„λ €μ„œ νŠ€λ©΄ λ˜λŠ”λ“―?? πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N, K; cin >> N >> K; vector<int> A(N); rep(i, 0, N) cin >> A[i]; vector<int> ans; priority_queue<int, vector<int>, greater<int>> PQ; rep(i, 0, N){ PQ.push(A[i]); if(PQ.size() > K){ ans.push_back(PQ.top()); PQ.pop(); } } while(!PQ.empty()){ ans.push_back(PQ.top()); PQ.pop(); } for(auto x: ans) cout << x << " "; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 28068 I Am Knowledge

·267 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/28068 🧐 κ΄€μ°° 및 μ ‘κ·Ό # μ§€κΈˆ μ–΄λ–€ 책을 읽을 수 있고, $a_k <= b_k$라면, 읽지 μ•Šμ„ μ΄μœ κ°€ μ—†λ‹€. λ‚˜λ¨Έμ§€ $a_k > b_k$듀인 책듀은 μ–΄μ°¨ν”Ό μ½μ„μˆ˜λ‘ 즐거움이 κ°μ†Œλ§Œ ν•˜λ―€λ‘œ, $a_k$κ°€ 큰거뢀터 μ°¨λ‘€λŒ€λ‘œ 읽으면 λ˜μ§€ μ•Šμ„κΉŒ? μ–΄λ–»κ²Œ κ·Έλ¦¬λ””ν•˜κ²Œ κ°€μ•Όν•˜μ§€? 두 μ±… $i, j$κ°€ μžˆλ‹€κ³  ν•΄λ³΄μž. μ΄λ•Œ, 두 책을 $i \rightarrow j$둜 읽기 μœ„ν•΄μ„  $F \geq a_i$ $F - a_i + b_i \geq a_j \rightarrow F \geq a_i + a_j - b_i$ λ”°λΌμ„œ $F \geq \max(a_i, a_i + a_j - b_i) = \text{Cost}_{i \rightarrow j}$ 같은 λ°©μ‹μœΌλ‘œ, $j \rightarrow i$둜 읽기 μœ„ν•΄μ„  $F \geq \max(a_j, a_i + a_j - b_j) = \text{Cost}_{j \rightarrow i}$ 이 λ•Œ, $b_i \geq b_j$라고 κ°€μ •ν•˜μž. $a_i < a_i + (a_j - b_j)$ $a_i + a_j - b_i \leq a_i + a_j - b_j$ 이 두 식이 μ„±λ¦½ν•˜λ―€λ‘œ, μ–Έμ œλ‚˜ $\text{Cost}_{i \rightarrow j} \leq \text{Cost}_{j \rightarrow i}$ λ”°λΌμ„œ $b$의 λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ ν›„ 그리디가 μ„±λ¦½ν•œλ‹€. πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N; cin >> N; vector<pii> v1, v2; rep(i, 0, N){ int a, b; cin >> a >> b; if(a <= b) v1.push_back({a, b}); else v2.push_back({a, b}); } sort(all(v1)); sort(all(v2), [](pii &p1, pii &p2){ return p1.second > p2.second; }); ll cur = 0; for(auto &p: v1){ if(cur < p.first){ cout << 0; return; } cur -= p.first; cur += p.second; } for(auto &p: v2){ if(cur < p.first){ cout << 0; return; } cur -= p.first; cur += p.second; } cout << 1; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 28448 κ΄‘κΈ°μ˜ PS

·205 words·1 min
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/28448 🧐 κ΄€μ°° 및 μ ‘κ·Ό # ν•œ λ¬Έμ œλ‹Ή κ΄‘κΈ°λŠ” $KT$만큼 μŒ“μ΄κ³ , ν•΄κ²°ν–ˆμ„λ•Œ $\text{min}(KT, 5K)$만큼 λΉ μ§€λ―€λ‘œ $T \leq 5$라면 문제λ₯Ό ν‘ΈλŠ”λ° κ΄‘κΈ°κ°€ μ•ˆμŒ“μΈλ‹€. 어라? μ•„λ‹ˆλ„€. $KT \leq L$ 쑰건도 ν•„μš”ν•˜λ‹€. μ•„ 이건 λ¬Έμ œμ‘°κ±΄μ— μžˆλ„€. μ•”νŠΌ 이 μΉœκ΅¬λ“€μ€ μ–΄μ°¨ν”Ό Tμ‹œκ°„ κ±Έλ €μ„œ ν’€κΈ°λ§Œ ν•˜λ©΄ 상관이 μ—†λ‹€. λ‚˜λ¨Έμ§€ λ¬Έμ œλ“€μ— λŒ€ν•΄, μ–΄μ°¨ν”Ό 문제λ₯Ό ν’€μ–΄μ„œ μŒ“μ΄λŠ” κ΄‘κΈ°μ˜ 합은 μΌμ •ν•˜λ‹€. κ·ΈλŸ¬λ‹ˆκΉŒ, 문제λ₯Ό ν•΄κ²°ν•΄μ„œ κ΄‘κΈ°λ₯Ό μ€„μ΄λŠ”κ±Έ νž˜λ‚΄μ•Όν•˜μ§€ μ•Šμ„κΉŒ? 그러면 κ΄‘κΈ°λ₯Ό 많이 ν•΄μ†Œν•  수 μžˆλŠ” 문제λ₯Ό λ¨Όμ € ν’€μ–΄μ•Όν•˜λŠ” κ±° 같은데… πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ ll N, L; cin >> N >> L; vector<pll> v; ll ans = 0; rep(i, 0, N){ ll K, T; cin >> K >> T; ans += T; if(T <= 5) continue; v.push_back({K, T}); } sort(all(v), [](pll a, pll b){ return min(a.first * a.second, 5 * a.first) > min(b.first * b.second, 5 * b.first); }); ll cur = 0; for(auto [K, T]: v){ if(cur + K*T > L){ ll rest = cur + K*T - L; ans += rest; cur -= rest; } cur += K*T; cur -= min(K*T, 5*K); } cout << ans; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 20136 λ©€ν‹°νƒ­ μŠ€μΌ€μ€„λ§ 2

·225 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/20136 🧐 κ΄€μ°° 및 μ ‘κ·Ό # κ·Έλ¦¬λ””ν•˜κ²Œ, λ½‘μ•„μ•Όν• λ•Œ κ³§ μ“Έλ§Œν•œκ±Έ 남기고, λ‚˜μ€‘μ— μ“Έλ§Œν•œκ±Έ λ½‘μœΌλ©΄ λ˜μ§€ μ•Šμ„κΉŒ? 증λͺ…ν•΄λ³΄μž. ν˜„μž¬ $N$개의 ꡬ멍이 κ½‰μ°¨μžˆκ³ , $A$λ₯Ό μƒˆλ‘œ κ½‚μ•„μ•Όν•œλ‹€κ³  κ°€μ •ν•˜μž. κ°€μž₯ λ‚˜μ€‘μ— μ“°λŠ”κ±Έ λ½‘λŠ” μ „λž΅ $G$κ°€ 있고, μ–΄λ–€ 졜적의 μ „λž΅ $Opt$κ°€ μžˆλ‹€κ³  κ°€μ •ν•˜μž. 이제 $G$κ°€ $Opt$보닀 λ‚˜μ˜μ§€ μ•ŠμŒμ„ 보이면 λœλ‹€. μ–΄λŠ μˆœκ°„, $A$λ₯Ό 꽂기 μœ„ν•΄ $G$λŠ” $X$λ₯Ό, $Opt$λŠ” $Y$λ₯Ό λ½‘μ•˜λ‹€. μ΄λ•Œ, 이후에 $X$κ°€ λ¨Όμ € λ“±μž₯ν•œλ‹€λ©΄, $G$λŠ” ν•œλ²ˆ 더 뽑/꼽을 μˆ˜ν–‰ν•΄μ•Όν•˜κ³ , $Opt$λŠ” μ•„λ‹ˆλ‹€. $Y$κ°€ λ¨Όμ € λ“±μž₯ν–ˆλ‹€λ©΄, $Opt$λŠ” 뽑/꼽을 μˆ˜ν–‰ν•΄μ•Ό ν•˜κ³ , $G$λŠ” μ•„λ‹ˆλ‹€. 그런데, $G$의 μ „λž΅ νŠΉμ„±μƒ $Y$보닀 $X$κ°€ 늦게 λ“±μž₯ν•΄μ•Όν•˜λ―€λ‘œ, μ–Έμ œλ‚˜ $Opt$보닀 $G$κ°€ λ‚˜μ˜μ§€ μ•Šλ‹€. πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N, K; cin >> N >> K; vector<queue<int>> nxt(K+1); vector<int> A(K); rep(i, 0, K) cin >> A[i]; rep(i, 0, K) nxt[A[i]].push(i); rep(i, 1, K+1) nxt[i].push(1e9); set<pii> st; // (nxt use, val) vector<bool> inuse(K+1, false); int ans = 0; rep(i, 0, K){ int val = A[i]; if(inuse[val]){ // 이미 κ½‚ν˜€μžˆλ‹€λ©΄ st.erase({i, val}); } // κ½‚ν˜€μžˆμ§€ μ•Šλ‹€λ©΄ else if((int)st.size() < N){ // 남은 μžλ¦¬κ°€ 있으면 inuse[val] = true; } else{ // 남은 μžλ¦¬κ°€ μ—†μœΌλ©΄ ans++; pii old = *st.rbegin(); st.erase(old); inuse[old.second] = false; inuse[val] = true; } nxt[val].pop(); if(!nxt[val].empty()) st.insert({nxt[val].front(), val}); } cout << ans << '\n'; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 10775 곡항

·145 words·1 min
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/10775 🧐 κ΄€μ°° 및 μ ‘κ·Ό # 1번 κ²Œμ΄νŠΈκ°€ 제일 μ“°κΈ° 쒋아보인닀. κ·ΈλŸ¬λ―€λ‘œ 1번 게이트λ₯Ό μ•„λ‚€λ‹€κ³  μƒκ°ν•˜λ©΄, λͺ¨λ“  λΉ„ν–‰κΈ°λ₯Ό λ„ν‚Ήμ‹œν‚¬λ•Œ 갈 수 μžˆλŠ” μ΅œλŒ“κ°’μœΌλ‘œ λ„ν‚Ήμ‹œν‚€λ©΄ λ˜λŠ” 것 κ°™λ‹€. 이λ₯Ό λ‚˜μ΄λΈŒν•˜κ²Œ κ΅¬ν˜„ν•˜λ©΄ ν•œλ²ˆλ‹Ή $O(G)$κ°€ 걸릴 것이닀. 100000 100000 100000 100000 100000 ... κ³Ό 같은 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€λ₯Ό 생각해보면 λœλ‹€. λ”°λΌμ„œ $\text{calc}(g_i) = g_i$ 보닀 μž‘κ±°λ‚˜ 같은 μ‚΄μ•„μžˆλŠ” 게이트의 μ΅œλŒ“κ°’μ„ λΉ λ₯΄κ²Œ 찾으면 λœλ‹€. μ΄λŠ” μœ λ‹ˆμ˜¨νŒŒμΈλ“œλ‘œ λΉ λ₯΄κ²Œ μˆ˜ν–‰ κ°€λŠ₯ν•˜λ‹€! mergeν• λ•Œ μžμ‹ λ³΄λ‹€ μž‘μ€ 값을 κ°€λ¦¬ν‚€κ²Œ ν•˜μž. πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int G, P; cin >> G >> P; UF.init(G+1); int ans = 0; while(P--){ int g; cin >> g; int rt = UF.find(g); if(rt == 0) break; UF.merge(rt, rt-1); ans++; } cout << ans << "\n"; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 14908 ꡬ두 μˆ˜μ„ κ³΅

·207 words·1 min
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/14908 🧐 κ΄€μ°° 및 μ ‘κ·Ό # μ§κ΄€μ μœΌλ‘œ μƒκ°ν•΄λ³΄μž μ–΄λ–€ μž‘μ—…μ˜ λ³΄μƒκΈˆ $S_i$κ°€ 크닀면, λΉ λ₯΄κ²Œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ”κ²Œ μ’‹λ‹€. μ–΄λ–€ μž‘μ—…μ„ μ™„λ£Œν•˜λŠ”λ° κ±Έλ¦¬λŠ” μ‹œκ°„ $T_i$κ°€ μž‘λ‹€λ©΄, λΉ λ₯΄κ²Œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ”κ²Œ μ’‹λ‹€. 이 두가지λ₯Ό μ–΄λ–»κ²Œ λ™μ‹œμ— ν™œμš©ν•  수 μžˆμ„κΉŒ? μ–΄λ–€ μ •λ‹΅ $Opt$κ°€ μ‘΄μž¬ν•œλ‹€κ³  κ°€μ •ν•΄λ³΄μž. μ΄λ•Œ, $Opt$의 μˆœμ„œμ€‘ κ°€μš΄λ° 두 μž‘μ—… $W_i, W_{i+1}$을 λ°”κΎΌλ‹€κ³  ν•΄λ³΄μž. 이 λ•Œ, 바뀐 μˆœμ„œ $Opt'$κ°€ $Opt$보닀 λ‚˜μ„ 수 μžˆμ„κΉŒ? 두 μž‘μ—…μ„ λ°”κΎΈλ©΄, $Opt' = Opt + S_i * T_{i+1} - S_{i+1} * T_i$κ°€ λœλ‹€. λ‹€μ‹œλ§ν•΄, $S_i * T_{i+1} - S_{i+1} * T_i$ 이 음수라면 더 λ‚˜μ€ 해법을 찾을 수 μžˆλ‹€. λ”°λΌμ„œ $S_i * T_{i+1} - S_{i+1} * T_i > 0$인 λ°©ν–₯, 즉 $\frac{S_i}{T_i} \geq \frac{S_{i+1}}{T_{i+1}}$ 의 μˆœμ„œλ‘œ μ •λ ¬ν•˜λ©΄ μ΅œμ ν•΄κ°€ λœλ‹€. πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ int N; cin >> N; vector<array<int, 3>> ans; // S, T, idx; rep(i, 0, N){ int S, T; cin >> S >> T; ans.push_back({T, S, i+1}); } sort(all(ans), [](const array<int, 3> &a, const array<int, 3> &b){ if(a[0]*b[1] == a[1]*b[0]) return a[2] < b[2]; return a[0]*b[1] > a[1]*b[0]; }); for(auto &p: ans) cout << p[2] << ' '; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금