백준 문제 풀이
백준 1168 요세푸스 문제 2
jwpassion1
2024. 10. 11. 13:37
https://www.acmicpc.net/problem/1168
요세푸스 문제는 매번 남은 수중 (현재 위치 + K) % 수의 개수 번째 수를 찾는 문제이다. 이는 세그먼트트리로 K번째 수를 찾는 연산과 존재하던 수를 지우는 연산을 구현해 풀 수 있다.
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
int res = 1;
vector<int> tree;
void init(int t1, int t2, int idx){
if (t1 == t2){
tree[idx] = 1;
return;
}
int mid = (t1 + t2) >> 1;
init(t1, mid, idx << 1);
init(mid + 1, t2, idx << 1 | 1);
tree[idx] = tree[idx << 1] + tree[idx << 1 | 1];
}
void init(int N){
tree.resize(res);
init(0, N - 1, 1);
}
void update(int t1, int t2, int q, int idx){
if (q < t1 || t2 < q) return;
if (t1 == t2){
tree[idx]--;
return;
}
int mid = (t1 + t2) >> 1;
update(t1, mid, q, idx << 1);
update(mid + 1, t2, q, idx << 1 | 1);
tree[idx] = tree[idx << 1] + tree[idx << 1 | 1];
}
int query(int t1, int t2, int K, int idx){
if (t1 == t2) return t1;
int mid = (t1 + t2) >> 1;
if (K < tree[idx << 1]) return query(t1, mid, K, idx << 1);
else return query(mid + 1, t2, K - tree[idx << 1], idx << 1 | 1);
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N, K;
cin >> N >> K;
while (res < N << 1){
res <<= 1;
}
init(N);
vector<int> ans;
int no = N - 1;
for (int i = N; i >= 1; i--){
no = (no + K) % i;
int qu = query(0, N - 1, no, 1);
no--;
update(0, N - 1, qu, 1);
ans.push_back(qu + 1);
}
cout << '<';
for (int i = 0; i < N; i++){
cout << ans[i];
if (i + 1 == N) cout << ">\n";
else cout << ", ";
}
}