문제: BOJ 19646 - Random Generator
각 숫자 \(i\)를 \(w_i\)번씩 “연속 배치”한 긴 수열에서, 매 단계 \(p_k\)번째 원소를 뽑아 순열에 추가하고 그 숫자의 남은 모든 복제본을 한 번에 제거한다.
이 과정을 \(N\)번 반복했을 때 최종 순열을 복원하는 문제다.
문제 정보
문제 링크: https://www.acmicpc.net/problem/19646
문제 요약:
- 처음에 숫자 \(1..N\)을 각각 \(w_i\)개씩 이어 붙여 길이 \(W=\sum w_i\)인 수열을 만든다.
- 각 단계 \(k\)에서 \(1..W\) 중 균등하게 고른 위치가 \(p_k\)로 주어질 때, 그 위치의 숫자를 답에 추가한다.
- 추가한 숫자의 모든 남은 등장을 수열에서 삭제하고, 수열이 빌 때까지 반복한다.
- \(p_1..p_N\)는 항상 “가능한 경우만” 주어진다.
제한 조건:
- 시간 제한: 1초
- 메모리 제한: 1024MB
- \(1 \le N \le 200{,}000\)
- \(1 \le w_i \le 1000\)
입출력 예제
입력 1:
| |
출력 1:
| |
접근 방식
핵심 관찰: “긴 수열”을 직접 만들 필요가 없다
처음 수열은
\[ \underbrace{1,1,\ldots}_{w_1\text{개}}, \underbrace{2,2,\ldots}_{w_2\text{개}}, \ldots, \underbrace{N,N,\ldots}_{w_N\text{개}} \]처럼 블록(구간)들의 연결이다. 어떤 숫자 \(x\)를 뽑는 순간, 그 숫자 블록 전체(\(w_x\)개)가 통째로 사라진다.
따라서 매 단계에 필요한 것은:
- 현재 남아 있는 각 숫자 \(i\)의 개수(가중치) \(w_i\) 와
- “블록들을 이어 붙였을 때 \(p_k\)번째가 어느 숫자에 속하는지”를 찾는 k-th(순서 통계) 질의
뿐이다.
이를 위해 Fenwick Tree(이진 인덱스 트리)에 \(w_i\)를 저장하면,
- prefix sum = 앞에서부터 몇 개가 남아 있는지
- k-th = prefix sum이 처음으로 \(p_k\) 이상이 되는 최소 인덱스
를 \(O(\log N)\)에 구할 수 있다.
알고리즘 설계 (Mermaid Flowchart)
flowchart TD
A["입력: N, w[1..N], p[1..N]"] --> B["Fenwick에 w로 초기화(sum = 총 남은 개수)"]
B --> C["k = 1..N 반복"]
C --> D["x = kth(p[k])(prefix sum >= p[k] 최소 x)"]
D --> E["ans에 x 추가"]
E --> F["Fenwick.add(x, -w[x])(x 블록 전체 제거)"]
F --> C
C --> G["ans 출력"]
단계별 로직
- Fenwick 초기화:
tree[i] += w[i] - 각 단계 k에서 선택: Fenwick의
kth(p[k])로 선택된 숫자 \(x\)를 찾는다. - 전체 삭제 반영:
add(x, -w[x])로 해당 블록을 0으로 만든다. - 총 N회 반복하면 정확히 \(1..N\)의 순열이 나온다. (각 숫자는 한 번만 선택됨)
정당성(간단 증명)
Fenwick에 저장한 값은 “현재 남아 있는 수열에서 숫자 \(i\)가 차지하는 길이”다.
- 불변식: 어느 시점이든, “남아 있는 긴 수열”에서 인덱스 \(t\)가 속한 숫자는 \(\min\{x \mid \sum_{i=1}^{x} w_i \ge t\}\) 이다.
- Fenwick의
kth(t)는 바로 위 정의의 최소 \(x\)를 \(O(\log N)\)에 찾는다. - 숫자 \(x\)를 뽑으면 문제 정의상 그 숫자의 남은 모든 복제본이 삭제되므로, 가중치 \(w_x\)를 0으로 만드는 업데이트가 정확하다.
따라서 각 단계에서 선택되는 숫자와 삭제 과정이 문제의 과정과 일치하며, \(N\)번 반복 후 얻는 수열은 요구되는 순열이다.
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(N \log N)\) | 각 단계 kth + add가 \(O(\log N)\) |
| 공간 복잡도 | \(O(N)\) | Fenwick + 입력 배열 |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| 큰 합 W | \(W=\sum w_i \le 2 \times 10^8\) | 누적합/bit는 long long 권장 |
| 이미 삭제된 숫자 | 한 번 뽑힌 숫자는 다시 등장하지 않음 | add(x, -w[x]) 후 w[x]=0 |
| p_k의 유효성 | 남은 길이보다 큰 \(p_k\)는 없음 | 입력이 보장하지만 kth는 1-index로 구현 |
| 1-index/0-index 혼동 | Fenwick은 보통 1-index | kth/add/입력 모두 1-index로 통일 |
구현 코드 (C++)
| |
참고 문헌 및 출처
작성 체크리스트
- 폴더명이
YYYY-MM-DD-BOJ-번호-슬러그형식인가? - Front Matter의 tags가 50개 이상인가? (한글/영어 포함)
- description이 150자 내외로 핵심을 요약했는가?
- Mermaid 다이어그램으로 로직을 시각화했는가? (라벨 특수문자 방지용 전체 따옴표 적용)
- 복잡도 분석이 표(Table) 형식인가?
- 코드 최상단에 지정 주석이 포함되었는가?
- 코너 케이스 체크리스트가 포함되었는가?
-
date와lastmod가 오늘 날짜(2026-02-05)로 설정되었는가?
![Featured image of post [Algorithm] C++ 백준 19646번: Random Generator](/post/algorithm/2026-02-05-boj-19646-random-generator-fenwick-tree-order-statistics-cpp-solution/wordcloud_hu_50d2e0c9f0185408.png)
![[Algorithm] C++ 백준 21814번: United Cows of Farmer John](/post/algorithm/2026-02-06-boj-21814-united-cows-of-farmer-john-fenwick-cpp-solution/wordcloud_hu_4a91d245f991ea37.png)
![[Algorithm] C++ 백준 13013번: 접미사 배열 2](/post/algorithm/2026-02-05-boj-13013-suffix-array-2-min-distinct-characters-cpp-solution/wordcloud_hu_bb3ccfbf206b5860.png)
![[Algorithm] C++ 백준 19646번: Random Generator](/post/algorithm/2026-02-05-boj-19646-random-generator-fenwick-tree-order-statistics-cpp-solution/wordcloud_hu_8da99d30b7997346.png)
![[Algorithm] C++ 백준 6194번: Building the Moat](/post/algorithm/2026-02-05-boj-6194-building-the-moat-convex-hull-cpp-solution/wordcloud_hu_7e1203d33ff8c8c0.png)
![[Algorithm] C++ 백준 12925번: Numbers](/post/algorithm/2026-01-30-boj-12925-numbers-matrix-exponentiation-cpp-solution/wordcloud_hu_3ddd9b1682d67718.png)
![[Algorithm] C++ 백준 1777번: 순열복원](/post/algorithm/2025-12-19-boj-1777-permutation-recovery-cpp-solution/wordcloud_hu_5cc423cda339f0d4.png)
![[Algorithm] C++ 백준 3006번: 터보소트](/post/algorithm/2025-12-19-boj-3006-turbosort-cpp-solution/wordcloud_hu_178815acefb3fc18.png)
![[Algorithm] C++ 백준 15517번: Array Manipulation at Moloco (Hard)](/post/algorithm/2026-01-30-boj-15517-array-manipulation-at-moloco-hard-fenwick-cpp-solution/wordcloud_hu_521deba1ba8bdbdd.png)
![[Algorithm] C++ 백준 13028번: 민호의 소원](/post/algorithm/2025-12-22-boj-13028-minhos-wish-fenwick-offline-cpp-solution/wordcloud_hu_23f3e1d2acd7bbf0.png)