이 문제는 \(10^5 \times 10^5\) 보드에서 2×2 블록 뒤집기를 무제한으로 사용할 때, 현재 상태를 목표 상태로 만들 수 있는지 판정하는 문제다.
핵심은 “행/열마다 색이 바뀐 칸의 개수의 홀짝(Parity)”이 연산으로 절대 바뀌지 않는다는 불변식이다.
문제 정보
문제 요약:
- 좌표가 \(1 \le x, y \le 10^5\) 인 \(10^5 \times 10^5\) 격자판이 있다.
- 현재 빨간 칸 \(N\)개와 목표 빨간 칸 \(M\)개의 좌표가 주어진다. (나머지는 노란 칸)
- 뒤집기 마법을 좌표 \((x,y)\) (\(1 \le x < 10^5\), \(1 \le y < 10^5\))에 사용하면,
- \((x,y), (x,y+1), (x+1,y), (x+1,y+1)\) 4칸의 색이 반전된다.
- 이 연산만으로 현재 상태를 목표 상태로 만들 수 있으면
YES, 아니면NO를 출력한다.
제한 조건:
- 시간 제한: 1초
- 메모리 제한: 1024MB
- \(1 \le N, M \le 10^5\)
접근 방식
핵심 관찰: 행/열 홀짝 불변식
어떤 \((x,y)\)에서 2×2를 뒤집으면,
- 행 \(x\)에서 2칸이 토글되고, 행 \(x+1\)에서도 2칸이 토글된다 → 각 행에서 토글된 칸 수는 항상 2(짝수)
- 열 \(y\)에서 2칸이 토글되고, 열 \(y+1\)에서도 2칸이 토글된다 → 각 열에서도 항상 짝수 개
따라서 어떤 연산을 몇 번 하더라도,
- 각 행에서 “색이 바뀐 칸 수의 홀짝”
- 각 열에서 “색이 바뀐 칸 수의 홀짝” 은 변하지 않는다.
현재/목표를 ‘대칭차’로 바꾸기
현재 상태에서 목표 상태로 바뀌어야 하는 칸들의 집합 \(D\)를 생각하자.
- \(D =\) (현재 빨간 칸 집합) \(\oplus\) (목표 빨간 칸 집합) (대칭차)
- 즉, \(D\)에 포함된 칸은 “반드시 색이 뒤집혀야 하는 칸”이다.
그러면 정답은 다음과 같이 판정할 수 있다:
- \(D\)에서 각 행에 포함된 칸 수가 모두 짝수이고,
- \(D\)에서 각 열에 포함된 칸 수가 모두 짝수이면
YES, - 하나라도 홀수면
NO.
이 조건은 위 불변식 때문에 필요 조건이며, 2×2 뒤집기 연산이 만들어내는 상태공간이 이 불변식으로 정확히 특징지어지므로 충분 조건이기도 하다.
알고리즘 설계 (Mermaid Flowchart)
flowchart TD
A["입력 N, M"] --> B["행/열 홀짝 배열과 odd 카운터 초기화"]
B --> C["현재 빨간 칸 N개를 읽으며 row[x], col[y] 토글"]
C --> D["목표 빨간 칸 M개를 읽으며 row[x], col[y] 토글"]
D --> E{"oddRow == 0 and oddCol == 0 ?"}
E -->|YES| F["YES 출력"]
E -->|NO| G["NO 출력"]
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(N+M)\) | 각 좌표를 한 번씩 처리 |
| 공간 복잡도 | \(O(10^5)\) | 행/열 홀짝 배열(1..10^5) |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| 중복 좌표 | 입력에서 같은 좌표가 반복되면 토글이 깨짐 | 문제에서 서로 다른 좌표임이 보장됨 |
| 큰 보드 크기 착각 | \(10^5\times10^5\) 전체를 만들면 메모리 초과 | 좌표 리스트만 읽고 홀짝만 관리 |
| (x,y) 범위 혼동 | 마법은 \(x<10^5, y<10^5\) | 불변식 판정에는 영향 없음(도달 가능 공간 동일) |
구현 코드
C++
| |
![Featured image of post [Algorithm] C++ 백준 25201번: 보드 뒤집기 게임](/post/algorithm/2025-12-19-boj-25201-board-flipping-game-cpp-solution/wordcloud_hu_6121b586cd694bb4.png)
![[Algorithm] C++ 백준 20506번: Kaisar - 생존](/post/algorithm/2025-12-19-boj-20506-kaisar-survival-cpp-solution/wordcloud_hu_1115df393a79effd.png)
![[Algorithm] C++ 백준 22878번: 간단한 문제](/post/algorithm/2025-12-19-boj-22878-simple-problem-cpp-solution/wordcloud_hu_9cd053bc1be8114a.png)
![[Algorithm] C++ 백준 25201번: 보드 뒤집기 게임](/post/algorithm/2025-12-19-boj-25201-board-flipping-game-cpp-solution/wordcloud_hu_22b1d8c414e9b6d9.png)
![[Algorithm] C++ 백준 2586번: 소방차](/post/algorithm/2025-12-19-boj-2586-firetruck-cpp-solution/wordcloud_hu_c7df555f7b0ecd9e.png)
![[Algorithm] C++ 백준 2988번: 아보가드로](/post/algorithm/2025-12-19-boj-2988-avogadro-cpp-solution/wordcloud_hu_504f3f1bc728ef52.png)
![[Algorithm] C++ 백준 32190번: Ian Sequences](/post/algorithm/2025-12-19-boj-32190-ian-sequences-cpp-solution/wordcloud_hu_266416599cd1461b.png)
![[Algorithm] C++ 백준 16895번: 님 게임 3](/post/algorithm/2025-12-19-boj-16895-nim-game-3-cpp-solution/wordcloud_hu_f071b137bed4b6a4.png)
![[Algorithm] C++ 백준 17965번: Absolute Game](/post/algorithm/2025-12-19-boj-17965-absolute-game-cpp-solution/wordcloud_hu_f6800a55fcd520be.png)