fragment-header
fragment-markdown
홈
로그인
로그아웃
내 블로그
설정
로그인
백준 1168 (C++) 요세푸스 문제 2
최초 업로드: 2025-04-19 10:36:20
최근 수정 시간: 2025-07-25 09:38:21
게시자: rlatjwls3333
카테고리: 백준
조회수: 9
# [Platinum III] 요세푸스 문제 2 #### [문제 링크](https://www.acmicpc.net/problem/1168) ## 문제 설명 <p>요세푸스 문제는 다음과 같다.</p> <p>1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.</p> <p>N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.</p> ## 입력 <p>첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 100,000)</p> ## 출력 <p>예제와 같이 요세푸스 순열을 출력한다.</p> ## 풀이 #### 해당 문제에서 더 빨리 원소를 빼내기 위해 arr[i]를 i번째까지의 원소의 개수로 두고 세그먼트 트리를 사용하면 됩니다. ``` c++ #include<bits/stdc++.h> using namespace std; const int MAX = 300'000; int _size=1, arr[MAX]; void update(int nodeNum) { arr[nodeNum]--; while(nodeNum>1) { nodeNum>>=1; arr[nodeNum] = arr[nodeNum*2] + arr[nodeNum*2+1]; } } int search(int nodeNum, int nodeL, int nodeR, int k) { if(nodeL==nodeR) { update(nodeNum); return nodeL+1; } int mid = (nodeL+nodeR)/2; if(k<=arr[nodeNum*2])return search(nodeNum*2, nodeL, mid, k); return search(nodeNum*2+1, mid+1, nodeR, k-arr[nodeNum*2]); } int main() { ios::sync_with_stdio(0); cin.tie(0); int n, k; cin >> n >> k; while(_size<n) _size<<=1; _size<<=1; for(int i=_size/2;i<_size/2+n;i++) arr[i]=1; for(int i=_size/2-1;i>0;i--) arr[i] = arr[i*2]+arr[i*2+1]; int last=1; for(int i=1;i<=n;i++) { if(i==1) cout << "<"; else cout << ", "; int next = (last-2+k)%arr[1]+1; cout << search(1, 0, _size/2-1, next); last = next; if(i==n) cout << ">"; } } ```