백준 2465번 줄 세우기
문제
N명의 사람들이 어떤 공연장에 입장하기 위해서 한 줄로 서 있다. 줄 서 있는 각 사람은 자기 앞에 서 있는 사람들 중에서 자기보다 키가 작거나 같은 사람들의 수를 알고 있다. 그러면, 이 수들을 표시하는 수열을 S라고 한다.
N명의 키 집합과 수열 S가 주어질 때, 원래 줄 서 있는 키 순서를 정확히 찾아내는 프로그램을 작성하시오.
예를 들어서, 사람들의 키 집합이 다음과 같이 주어진다 (여기서, 같은 키의 사람들이 여러 명 존재할 수 있어서 중복이 포함된다).
{120, 167, 163, 172, 145, 134, 182, 155, 167, 120, 119, 156}
또한 각 사람이 자기 앞에 있는 사람들 중에서 자기보다 키가 작거나 같은 사람들의 수를 표시하는 수열 S는 다음과 같이 주어진다.
S : 0 1 0 0 3 2 6 7 4 6 9 4
그러면, 실제 줄 서 있는 사람들의 키 순서는 다음과 같다.
134 167 120 119 156 120 167 182 155 163 172 145
문제풀이
(0) 생각
Index |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
키 |
119 |
120 |
120 |
134 |
145 |
155 |
156 |
163 |
167 |
167 |
172 |
182 |
순서 |
0 |
1 |
0 |
0 |
3 |
2 |
6 |
7 |
4 |
6 |
9 |
4 |
누구꺼 |
|
|
|
|
|
|
|
|
|
|
|
|
Index |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
키 |
119 |
120 |
120 |
134 |
145 |
155 |
156 |
163 |
167 |
167 |
172 |
182 |
순서 |
0 |
1 |
0 |
0 |
3 |
2 |
6 |
7 |
4 |
6 |
9 |
4 |
누구꺼 |
|
|
|
|
11 |
|
|
|
|
|
|
|
Index |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
키 |
119 |
120 |
120 |
134 |
145 |
155 |
156 |
163 |
167 |
167 |
172 |
182 |
순서 |
0 |
1 |
0 |
0 |
3 |
2 |
6 |
7 |
4 |
6 |
9 |
4 |
누구꺼 |
|
|
|
|
11 |
|
|
|
|
|
10 |
|
Index |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
키 |
119 |
120 |
120 |
134 |
145 |
155 |
156 |
163 |
167 |
167 |
172 |
182 |
순서 |
0 |
1 |
0 |
0 |
3 |
2 |
6 |
7 |
4 |
6 |
9 |
4 |
누구꺼 |
|
|
|
|
11 |
|
|
9 |
|
|
10 |
|
Index |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
키 |
119 |
120 |
120 |
134 |
145 |
155 |
156 |
163 |
167 |
167 |
172 |
182 |
순서 |
0 |
1 |
0 |
0 |
3 |
2 |
6 |
7 |
4 |
6 |
9 |
4 |
누구꺼 |
3 |
2 |
5 |
0 |
11 |
8 |
4 |
9 |
1 |
6 |
10 |
7 |
(1) 코드 34~37
(2) 코드 17~26
#include <bits/stdc++.h> | |
using namespace std; | |
const int MAX = 1 << 17; | |
int N; | |
int tall[MAX]; | |
int sequence[MAX]; | |
int ans[MAX]; | |
int segtree[2 * MAX]; | |
void update(int x) { | |
while (x > 0) { | |
segtree[x]++; | |
x /= 2; | |
} | |
} | |
// s~e 범위에서 wanna의 키를 갖은 사람이 몇번째로 큰 사람인지 구하는 함수 | |
int path(int wanna, int idx = 1, int s = 0, int e = MAX - 1) { | |
if (idx >= MAX) return idx - MAX; // 기저 (wanna의 키를 갖은 사람이 들어갈 자리) | |
int mid = (s + e) / 2; | |
int left_seat = (mid - s + 1) - segtree[2 * idx]; // 왼쪽에 남은 자리 | |
if (left_seat >= wanna) return path(wanna, 2 * idx, s, mid); | |
else return path(wanna - left_seat, 2 * idx + 1, mid + 1, e); | |
} | |
int main() {ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> N; | |
for (int i = 0; i < N; ++i) cin >> tall[i]; // 실제 키 | |
for (int i = 0; i < N; ++i) cin >> sequence[i]; // 앞에 있는 작은 사람 수 수열 | |
sort(tall, tall + N); // 키순으로 정렬 | |
for (int i = N - 1; i >= 0; i--) { // 뒤에서 부터 탐색 | |
ans[i] = path(sequence[i] + 1); | |
update(MAX + ans[i]); // 해당 키 가져갔음을 체크 | |
} | |
for (int i = 0; i < N; ++i) cout << tall[ans[i]] << '\n'; | |
return 0; | |
} |
깔끔한 풀이네요. 잘 보고 갑니다.
답글삭제