본문 바로가기

삼성전자 알고리즘/백준온라인

5. 10755 컴퓨터실

원본 출처 : https://www.acmicpc.net/problem/10755

 

10755번: 컴퓨터실

문제 CSHS(Computer Science High School)의 실습실에는 총 M대의 컴퓨터가 일렬로 놓여있다. 이 컴퓨터는 왼쪽에 있는 것부터 순서대로 1~M의 번호가 매겨져 있다. 현재, 이 실습실에는 총 N명의 학생들이 이미 앉아있으며, 각각 A1, A2, ..., AN번 컴퓨터 앞에 앉아있다. 곧 있으면 자습시간이 시작되기 때문에 총 M-N명의 학생이 더 와서 컴퓨터를 사용할 것이다. 각 학생들은 다른 학생이 자기 컴퓨터의 모니터를 보는 것을

www.acmicpc.net

문제 풀이 : 

// 힙 자료구조 활용 - 컴퓨터
 
#include <stdio.h>
#define MAX 300000
int M, N, Q;
int A[MAX + 1]; // 기존학생과 마지막 친구의 순번까지의 앉은 컴퓨터 자리 기록
int B[1000001]; // Q명의 친구들의 순번
int tmp[MAX + 1];   //merge_sort에 사용될 임시 배열
void merge_sort(int s, int e) {
    if (s >= e) return;
    int m = (s + e) / 2;
    //분할
    merge_sort(s, m);
    merge_sort(m + 1, e);
    //정복
    int l_p = s, r_p = m + 1, t_p = s;
    while (l_p <= m && r_p <= e) {
        //비교
        if (A[l_p] < A[r_p]) {
            tmp[t_p++] = A[l_p++];
        }
        else {
            tmp[t_p++] = A[r_p++];
        }
    }
    //남은 것들
    while (l_p <= m) {
        tmp[t_p++] = A[l_p++];
    }
    while (r_p <= e) {
        tmp[t_p++] = A[r_p++];
    }
    //tmp배열을 원 배열로 복사
    for (t_p = s; t_p <= e; t_p++) {
        A[t_p] = tmp[t_p];
    }
}
 
typedef struct {
    int s, e, cnt;
}NODE;
 
NODE heap[MAX + 1]; // 0번 방 사용 하지 않는 것 고려
int last = 0;
 
int comp(int x, int y) { // x : 부모(왼쪽), y : 자식(오른쪽)
    if (heap[x].cnt > heap[y].cnt) return 1;
    else if (heap[x].cnt == heap[y].cnt && heap[x].s < heap[y].s) return 1;
    else return 0;
}
 
 
int push(int s, int e, int cnt) {
    int p, c;
    NODE temp;
    if (last == MAX) return 0; //full 조건
    last++;
    heap[last].s = s;
    heap[last].e = e;
    heap[last].cnt = cnt;
 
    c = last; p = c / 2; // 부모와 자식의 위치 정함
    while (p > 0) { // 부모가 최상위 노드까지 경쟁시켜야함
        if (comp(c, p) == 1) {
            temp = heap[p];
            heap[p] = heap[c];
            heap[c] = temp;
            c = p; p = c / 2;
        }
        else break;
    }
    return 1;
}
 
int pop(NODE *d) {
    int p, l, r, c;
    NODE  temp;
    if (last == 0) return 0; // empty 조건
    *d = heap[1]; // 최상위 노드 전달
    heap[1] = heap[last]; // 마지막 노드를 최상위노드로 배치
    last--;
    p = 1; l = 2 * p; r = l + 1;
    while (l <= last) {
        if (l == last) c = l; // 자식이 1명인 경우
        else if (comp(l, r) == 1) c = l; // 자식이 2명인 경우, 더큰 값을 후보자로
        else c = r;
        if (comp(c, p) == 1) {
            temp = heap[p];
            heap[p] = heap[c];
            heap[c] = temp;
            p = c; l = 2 * p; r = l + 1;
        }
        else break;
    }
    return 1;
}
 
int main(void) {
 
    int i, s, e, cnt;
    NODE d;
    scanf("%d %d %d", &M, &N, &Q);
    for (i = 1; i <= N; i++) { scanf("%d", &A[i]); } // 기존 자리잡은 학생의 컴위치
    for (i = 1; i <= Q; i++) { scanf("%d", &B[i]); } // 친구들의 순번
    //merge_sort(0, N - 1); //A배열을 sorting 해준다.
    for (i = 1; i <= N; i++) { // 앞에서부터 빈자리의 그릅을 힙트리에 push
        s = A[i - 1] + 1;
        e = A[i] - 1;
        cnt = e - s + 1;
        push(s, e, cnt);
    }
    // 맨 끝 마지막 그룹 push
    push(A[N] + 1, M, M - A[N]);
 
    for (i = N + 1; i <= B[Q]; i++) { // 기존 앉은 학생의 순번 다음부터 친구 마지막 순번까지만 탐색
        // pop한 그룹의 mid자리에 i번째 학생을 앉히고 왼쪽, 오른쪽 그룹을 다시 push
        pop(&d);
        int m = (d.s + d.e) / 2;
        A[i] = m;
        if (d.s < m) push(d.s, m - 1, m - 1 - d.s + 1); // 왼쪽 그룹 푸쉬
        if (m < d.e) push(m + 1, d.e, d.e - (m + 1) + 1); // 오른쪽 그룹 푸쉬
    }
 
    for (i = 1; i <= Q; i++) { printf("%d\n", A[B[i]]); } // Q명의 친구가 앉은 컴위치 인쇄
 
    return 0;
}

'삼성전자 알고리즘 > 백준온라인' 카테고리의 다른 글

7. 5052 전화번호 목록  (0) 2019.06.28
6. 3653 영화 수집  (0) 2019.06.28
4. 11066 파일 합치기 [힙]  (0) 2019.06.16
3. 2805 나무 자르기  (0) 2019.06.16
2. 2961 도영이가 만든 맛있는 음식  (0) 2019.05.09