📝 문제 정보 # 링크: https://www.acmicpc.net/problem/31740 🧐 관찰 및 접근 # 문제에서 주어진 그래프는 트리로 보인다. 트리에서는 모든 간선이 단절선이므로 하나만 잘라도 두 컴포넌트로 나뉘는것이 자명하다. 간선을 하나 자르고 나면 서브트리 하나와 나머지 부분으로 나뉜다. 서브트리의 가중치는 트리DP를 활용해 미리 계산해둘 수 있고, 나머지 부분은 전체 가중치 합에서 해당 서브트리의 가중치 합만큼을 빼면 된다. $O(N)$에 계산 가능해보인다. 💻 풀이 # 코드 (C++): int dfs(int c, int p){ par[c] = p; DP[c] = W[c]; for(auto nxt : links[c]){ if(nxt == p) continue; DP[c] += dfs(nxt, c); } return DP[c]; } void solve(){ cin >> N; rep(i, 0, N-1){ int u, v; cin >> u >> v; links[u].push_back(v); links[v].push_back(u); } rep(i, 1, N+1) cin >> W[i]; int SUM = dfs(1, -1); int ans = 2e9; pii ans2 = {-1, -1}; rep(i, 2, N+1) if(ans > abs(DP[i] - (SUM - DP[i]))){ ans = abs(DP[i] - (SUM - DP[i])); ans2 = {i, par[i]}; } cout << ans << '\n'; cout << ans2.first << ' ' << ans2.second << '\n'; } 🔒 구현 코드 잠금
📝 문제 정보 # 링크: https://www.acmicpc.net/problem/2437 🧐 관찰 및 접근 # $1, 2, 4, 8, 16, \cdots$의 추로 모든 양의 정수를 측정할 수 있음이 자명하다. 이 이유를 살펴보면, $X$라는 무게의 추가 있을때, $X-1$까지의 모든 정수를 표현할 수 없다면 표현할 수 있는 최대치 + 1이 답이 된다. 추를 작은것부터 정렬해서, 빠지는 수 없이 무슨 양의 정수까지 최대한 잴 수 있는지 확인하자. 💻 풀이 # 코드 (C++): void solve(){ int N; cin >> N; vector<ll> v(N); rep(i, 0, N) cin >> v[i]; sort(all(v)); ll sum = 0; rep(i, 0, N){ if(v[i] > sum + 1){ cout << sum + 1 << "\n"; return; } sum += v[i]; } cout << sum + 1 << "\n"; } 🔒 구현 코드 잠금
📝 문제 정보 # 링크: https://www.acmicpc.net/problem/14464 🧐 관찰 및 접근 # 소에 대해서는 끝나는 시간이 가장 빠른 소를, 닭에 대해서는 가장 $T$가 빨리 오는 닭을 쓰는 그리디가 성립한다. 이를 구현하는 방법은 여러가지가 있겠지만, 여기서는 multiset과 이분탐색을 이용하겠다. 💻 풀이 # 코드 (C++): void solve(){ int C, N; cin >> C >> N; multiset<int> chicken; rep(i, 0, C){ int x; cin >> x; chicken.insert(x); } vector<pii> cow(N); rep(i, 0, N) cin >> cow[i].first >> cow[i].second; sort(all(cow), [](pii a, pii b){ return a.second < b.second; }); int ans = 0; for(auto [s, e]: cow){ auto it = chicken.lower_bound(s); if(it != chicken.end() && *it <= e){ ans++; chicken.erase(it); } } cout << ans << '\n'; } 🔒 구현 코드 잠금
📝 문제 정보 # 링크: https://www.acmicpc.net/problem/11000 🧐 관찰 및 접근 # 각 강의를 선분이라고 생각하면, 선분이 가장 많이 겹쳐진 타이밍이 가장 많은 강의실을 필요로 하는 타이밍일 것이다. 스위핑을 사용해서 이를 계산하자. 💻 풀이 # 코드 (C++): void solve(){ int N; cin >> N; vector<pair<int, bool>> events; // {time, isStart} rep(i, 0, N){ events.push_back({s, true}); events.push_back({e, false}); } sort(all(events)); int ans = 0, cnt = 0; for(auto [time, isStart]: events){ if(isStart) cnt++; else cnt--; ans = max(ans, cnt); } cout << ans; } 🔒 구현 코드 잠금
📝 문제 정보 # 링크: https://www.acmicpc.net/problem/31498 🧐 관찰 및 접근 # 집 - 토카 - 돌돌이 형태로 있는 것 같다. 매 수행마다 토카는 $B, B-K, B-2*K \cdots$ 만큼 움직이고, 돌돌이는 $D$만큼 계속 움직인다. 토카가 잡힌다면, 그 순간 토카가 움직인 길이는 $D$보다 작을 것이다. 따라서 토카가 어느 순간 잡혔다면, 토카와 돌돌이가 계속 움직인다고 가정하면 돌돌이는 토카보다 훨씬 왼쪽에 있게 된다. 따라서 시간에 토카와 돌돌이의 위치에 단조성이 존재한다. 이분 탐색을 이용할 수 있겠다. 토카가 집에 도착하지도 못하는 상황, $K$가 0인상황 등 여러가지 예외 상황을 조심하자. 💻 풀이 # 코드 (python): A, B = map(int, input().split()) C, D = map(int, input().split()) K = int(input()) # 토카가 집에 도착할 수는 있는가? # B + (B-K) + (B-2K) + ... >= A if K > 0: # K = 0이면 무조건 도착할 수 있음 cnt = B // K # B - cnt * K >= 0 인 최대 cnt tot = B * (cnt + 1) - K * (cnt * (cnt + 1)) // 2 # B + (B-K) + ... + (B - cnt * K) if tot < A: print(-1) exit(0) # 토카가 집에 도착하는 타이밍이 돌돌이보다 이른가? def toka_move(time): if K > 0: time = min(time, B // K + 1) return B * time - K * (time * (time - 1)) // 2 ok, ng = 10**12, 0 # 토카가 집에 도착하는 가장 빠른 타이밍 while ok - ng > 1: mid = (ok + ng) // 2 if toka_move(mid) >= A: ok = mid else: ng = mid if D*ok < A + C: # 아직 돌돌이가 도착하지 않았다면 print(ok) else: print(-1) 🔒 구현 코드 잠금
📝 문제 정보 # 링크: https://www.acmicpc.net/problem/27421 번역 문제 # Taro는 장난감 철도 선로 세트를 가지고 놀고 있습니다. 모든 선로는 직각 중심각(90도 각도)을 가진 호 모양이지만, 반지름은 다양합니다. Taro는 이 모든 선로를 사용하여 하나의 루프를 만들려고 합니다. 여기서 선로 세트가 하나의 루프를 형성한다는 것은 모든 선로의 양 끝이 다른 선로와 부드럽게 연결되고, 모든 선로가 직접 또는 간접적으로 다른 모든 선로와 연결되어 있을 때를 의미합니다. Taro가 이것을 달성할 수 있는지 여부를 알려주세요.