앳코더 ABC 450 후기
tkd0711 · 2026. 3. 21.
AtCoder Beginner Contest 450
https://atcoder.jp/contests/abc450
- 날짜: 2026-03-21 (Sat)
- 결과: A~C AC, D 미해결
- B: 6트
- C: 1트
- D: 런타임 에러 후 종료
1. 전체 느낌
이번 대회는 결과만 보면 A~C까지 풀고 600점이지만,
체감상은 최근 대회들 중 가장 아쉬운 편이었다.
A는 빠르게 해결했지만,
B에서 문제를 잘못 읽어서 6번이나 제출했고,
그 여파로 전체 흐름이 크게 꼬였다.
C는 다행히 원트로 풀었지만 문제 이해에 시간이 걸렸고,
D는 아이디어를 잡고 코드까지 썼는데 구현/자료구조 디테일 때문에 놓쳤다.
즉, 이번 대회는
- 문제를 못 봤다기보다는
- 문제 독해와 구현 디테일에서 계속 손실이 났던 대회
였다.
2. A – 빠른 시작
A는 큰 고민 없이 해결했다.
최근처럼 A는 비교적 안정적으로 처리되고 있고,
이번에도 초반 스타트 자체는 나쁘지 않았다.
3. B – Split Ticketing: 문제를 잘못 읽어서 크게 꼬임
문제 요약
정수 a < b < c를 골라서
a → bb → c
로 나눠 타는 비용이a → c로 한 번에 가는 비용보다 작은 경우가 존재하는지 판별하는 문제였다.
내가 처음 잘못 이해한 부분
처음에는 이걸
a = 1c = N
처럼 양끝이 고정된 상태에서
중간의 b만 찾는 문제처럼 이해했다.
그래서 사실상 1차원 반복문처럼 접근했다.
하지만 실제 문제는
a, b, c모두 자유롭게 고를 수 있는 존재 판별 문제
였다.
즉,
- 시작점도 아무 역이나 가능
- 끝점도 아무 역이나 가능
- 중간 역도 아무 역이나 가능
한 문제였는데,
내가 혼자 경우를 너무 좁게 해석하고 시작한 것이다.
왜 6트까지 갔는가
처음 문제 모델을 잘못 잡으니,
그 뒤에는 구현을 조금씩 고쳐도 계속 WA가 날 수밖에 없었다.
이 문제는 사실 N도 작아서
그냥 a, b, c를 전부 다 돌려보면 되는 문제였는데,
내가 처음부터 틀린 문제를 풀고 있었던 셈이다.
교훈
이번 B의 핵심 교훈은 아주 명확했다.
there existfor someany
같은 표현이 나오면
먼저 변수가 전부 자유로운지,
아니면 특정 값이 고정되는지를 정확히 읽어야 한다.
이번에는 존재형 문제를
내가 임의로 “양끝 고정” 문제로 바꿔서 읽은 것이 치명적이었다.
4. C – Puddles: 알고리즘보다 문제 해석에서 시간 사용
문제 요약
격자에서 흰색 칸들의 연결 요소 중,
가장 바깥 경계(1행, H행, 1열, W열)에 닿지 않는 것의 개수를 세는 문제였다.
처음 느낀 어려움
처음에는 “검은색에 둘러싸인 흰색 영역”이라는 표현 때문에
이걸 직접 판별해야 하나 싶어서 문제 이해에 시간이 걸렸다.
즉,
- 주변이 전부
#인지 봐야 하나? - 각 칸별로 둘러싸였는지 따져야 하나?
이런 식으로 받아들여서 초반에 잠깐 헷갈렸다.
실제 핵심
실제로는 훨씬 단순했다.
흰색 연결 요소를 BFS/DFS로 구한 뒤,
그 연결 요소가 바깥 경계에 닿는지만 보면 된다.
즉 “검은색에 둘러싸였다”를 직접 검사하는 게 아니라,
바깥 경계에 닿지 않는 흰색 컴포넌트 수를 세는 문제였다.
이 구조를 파악한 뒤에는 원트로 해결했다.
교훈
이번 C는 아이디어가 어려웠던 문제는 아니었다.
오히려 핵심은
- 문제를 어떻게 번역하느냐
- 조건을 어떤 형태로 재해석하느냐
였다.
문장을 정확히 읽어서
“둘러싸였다”를 “바깥 경계에 닿지 않는다”로 바꿀 수 있느냐가 중요했다.
5. D – Minimize Range: 아이디어는 잡았지만 구현 디테일로 놓침
문제 요약
수열의 각 원소에 대해
원할 때마다 K를 더할 수 있을 때,
최종적으로 max(A) - min(A)의 최솟값을 구하는 문제였다.
대회 중 생각한 방향
대회 중에는 문제 구조를 어느 정도 이해했고,
그에 맞춰 코드를 작성했다.
TreeSet을 사용해서
현재 가능한 값들의 최소/최대를 관리하는 방식으로 접근했다.
코드의 핵심 부분은 대략 이런 식이었다.
long a = tree.pollFirst();
long b = tree.getLast();
ans = Math.min(ans, b-a);
tree.add(a+m);
그런데 이 코드에서 런타임 에러가 발생했다.
대회 끝나고 바로 보인 문제
대회가 끝난 뒤 다시 생각해보니
문제가 바로 보였다.
pollFirst()를 먼저 해버리면
set이 비는 순간 getLast()를 호출할 수 없게 된다.
그래서 최소/최대는 먼저 확인하고,
그 다음 갱신/삭제를 해야 했다.
즉 순서는 이렇게 되어야 했다.
long a = tree.getFirst();
long b = tree.getLast();
ans = Math.min(ans, b-a);
tree.add(a+m);
tree.pollFirst();
이걸 대회 중에 바로 못 본 게 너무 아쉬웠다.
추가로 놓친 점
사실 이 문제에서 TreeSet 자체도 조심해야 했다.
TreeSet은 중복 값을 보존하지 않기 때문에,
같은 값이 여러 번 등장할 수 있는 상황에서는
멀티셋처럼 쓰면 안 된다.
즉 이번 D는 단순히 런타임 에러뿐 아니라,
- 최소값을 꺼내는 순서 문제
TreeSet의 중복 미보존 문제
이 둘 다 잠재적으로 있었던 셈이다.
왜 더 아쉬웠는가
이 문제는 아예 방향을 못 잡은 건 아니었다.
오히려 아이디어를 어느 정도 잡고, 코드도 거의 다 쓴 상태였다.
그래서 더 아쉽다.
- 알고리즘을 못 떠올린 것도 아니고
- 문제를 못 읽은 것도 아니고
- 구현 디테일과 자료구조 감각에서 놓친 문제
였기 때문이다.
대회 끝난 뒤 몇 분 지나서
“어디가 틀렸는지 바로 보이는” 유형이라 더 아프게 남는다.
6. 이번 대회에서 느낀 점
이번 ABC 450은
A~C까지 풀었지만 만족감은 거의 없었다.
그 이유는 명확하다.
- B: 문제를 잘못 읽어서 리듬이 무너짐
- C: 다행히 원트했지만 해석에 시간 사용
- D: 아이디어를 잡고도 구현 디테일로 놓침
즉 이번 대회는
실력이 전혀 없어서 못한 대회라기보다는,
문제 독해와 구현 디테일에서 계속 손해 본 대회
였다.
7. 다음 목표
- 존재 판별 문제에서
변수들이 전부 자유로운지 먼저 체크하기 - 문제 문장을 직접 구현하려 하지 말고,
더 간단한 조건으로 재해석할 수 있는지 보기 TreeSet을 멀티셋처럼 써도 되는지 항상 확인하기- 최소/최대 자료구조를 쓸 때
갱신 순서와 비어 있는 경우를 한 번 더 점검하기
한 줄 정리
ABC 450은 알고리즘을 아예 못 봐서 망한 대회가 아니라,
문제를 잘못 읽고 구현 디테일에서 계속 손해 보면서 아쉬움이 크게 남은 대회였다.