컴퓨터실

컴퓨터 실습실에는 총 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;
}

댓글

이 블로그의 인기 게시물

어민

최소비용 포장

구슬집어넣기