컴퓨터실
컴퓨터 실습실에는 총 M대의 컴퓨터가 일렬로 놓여있다. 이 컴퓨터는 왼쪽에 있는 것부터 순서대로 1~M의 번호가 매겨져 있다.
현재, 이 실습실에는 총 N명의 학생들이 이미 앉아있으며, 각각 들어온 순서에 따라 A1, A2, ..., AN번 컴퓨터 앞에 앉아있다. 곧 있으면 자습시간이 시작되기 때문에 총 M-N명의 학생이 더 와서 컴퓨터를 사용할 것이다.
각 학생들은 다른 학생이 자기 컴퓨터의 모니터를 보는 것을 싫어하므로 다음과 같은 방법으로 자리를 잡을 것이다.
1. 우선 학생이 없는 연속한 컴퓨터들의 그룹 중 가장 컴퓨터가 많은 그룹을 선택한다. 만약 이런 그룹이 여러 개라면 가장 왼쪽에 있는 그룹을 선택한다.
2. 그 다음, 선택한 그룹의 컴퓨터들 중 정 중앙에 있는 컴퓨터를 선택하여 자리를 잡는다. 만약 학생이 선택한 그룹의 컴퓨터가 짝수개인 경우 정 중앙 2개의 컴퓨터 중 왼쪽에 있는 컴퓨터에 자리를 잡는다.
정환이는 Q명의 친구들과 함께 팀 프로젝트를 해야 하기 때문에 Q명의 친구들이 어디에 앉을 지 알아야 한다. 다행히 정환이는 각 친구가 몇 번째로 실습실에 들어갔는지 알고 있다. 정환이를 도와 각 친구들의 위치를 구하시오.
입력
첫 번째 줄에는 컴퓨터의 수 M, 이미 자리를 잡은 학생의 수 N, 친구의 수 Q가 주어진다.
두 번째 줄에는 N개의 정수가 주어지는데, 이 값은 자리를 잡은 학생의 위치 Ai를 나타낸다. 이미 자리를 잡은 학생들은 앞서 말한 방법으로 자리를 잡지 않았을 수도 있음에 유의하여라.
세 번째 줄에는 Q개의 정수가 주어지는데, 이 값은 각 친구가 실습실에 들어간 순서 Bi를 의미한다. ( 이미 자리를 잡은 학생들 N명 중 정환이의 친구가 있을 수도 있다. )
1 ≤ A1 < A2 < . . . < AN ≤ M, 1 ≤ B1 < B2 < . . . < BQ ≤ M.
1 ≤ Q ≤ 105, N ≤ M, 1 ≤ N ≤ 105, 1 ≤ M ≤ 3*105
출력
출력은 총 Q개의 줄로 이루어진다. i번째 줄에는 i번째 친구가 자리잡은 컴퓨터의 번호를 출력한다.
입력 예시
7 1 4
4
2 3 4 5
출력 예시
2
6
1
3
#include <stdio.h>
struct data
{
int gap, start;
}heap[300010];
int a[300010], b[100010];
int last;
int M, N, Q; //컴퓨터의 수 M, 이미 자리를 잡은 학생의 수 N, 친구의 수 Q
int comp(int i, int j)
{
if (heap[i].gap == heap[j].gap) return heap[j].start - heap[i].start;
return heap[i].gap - heap[j].gap;
}
void swap(int a, int b)
{
struct data temp = heap[b];
heap[b] = heap[a];
heap[a] = temp;
}
void push(int g, int s)
{
heap[++last].gap = g;
heap[last].start = s;
for (int i = last; i > 1 && comp(i, i / 2)>0; i /= 2) {
swap(i, i / 2);
}
}
struct data pop(void)
{
swap(1, last);
last--;
for (int i = 1, j = 2; j <= last; i = j, j *= 2) {
if (j + 1 <= last && comp(j + 1, j)>0) j++;
if (comp(i, j)<0) swap(i, j);
else break;
}
return heap[last + 1];
}
int main(void)
{
struct data d;
int e, n;
int k = 0, cnt;
scanf("%d %d %d", &M, &N, &Q);
for (int i = 1; i <= N; i++) {
scanf("%d", &a[i]);
push(a[i] - a[i - 1] - 1, a[i - 1] + 1);
}
push(M - a[N], a[N] + 1);
for (int i = 1; i <= Q; i++) scanf("%d", &b[i]);
for (int i = N + 1; i <= b[Q]; i++) {
d = pop();
e = d.start + d.gap - 1;
n = (d.start + e) / 2;
a[i] = n;
if (n > d.start)push(n - d.start, d.start);
if (e > n)push(e - n, n + 1);
}
for (int i = 1; i <= Q; i++) {
printf("%d\n", a[b[i]]);
}
return 0;
}
댓글
댓글 쓰기