[ 백준 ] 2493 / 탑

金弘均·2021년 9월 16일
0

Baekjoon Online Judge

목록 보기
180/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 2493 / 탑
 *
 * Kind :: Data Structure
 *
 * Insight
 * - 그러니까... 결국
 *   현재 탑의 위치보다 크고 현재 탑의 왼쪽에 있으면서 가장 가까운 탑의 위치를 찾아야 한다
 *   + for 문 두 번 돌려서 찾으면 되지 않을까? <= O(n^2)
 *     # 1 2 3 4 5 ... N 과 같은 입력이 들어왔을 때 시간초과가 일어날 수밖에 없다
 *       -> 흐음...
 *
 * - 다음과 같은 입력이 들어왔다고 하자
 *   6 9 5 7 4 8
 *   + 일단 생각하기 쉽게 가장 왼쪽에 무한의 탑을 세우자
 *     INF 6 9 5 7 4 8 <= 높이
 *       0 1 2 3 4 5 6 <= 인덱스
 *     이러면, 레이저 신호를 수신하지 않는 탑은 저 INF 탑이 수신하게 된다
 *     (고맙게도 무한의 탑을 인덱스 0 으로 해도 나머지 탑의 인덱스에 영향을 주지 않는다)
 *     # INF
 *       INF 6
 *       => 6 은 INF 에 수신됨
 *       INF 6 9
 *       => 9 는 INF 에 수신됨
 *       INF 6 9 5
 *       => 5 는 9 에 수신됨
 *       INF 6 9 5 7
 *       => 7 은 9 에 수신됨
 *       -> 즉, 더 높은 탑이 다음에 오면 (6 다음 9, 5 다음 7)
 *          그 전에 있었던 탑들 중 위의 탑보다 작은 탑들은 의미가 없다
 *
 * - 의미없다 => 없애보자
 *   6 9 5 7 4 8
 *   + INF 6 9 5 7 4 8
 *     # INF
 *       INF 6                      (6 은 INF 에 수신됨)
 *       INF 6 9 => INF 9           (6 은 더이상 의미없음, 9 는 INF 에 수신됨)
 *       INF 9 5                    (5 는 INF 에 수신됨)
 *       INF 9 5 7 => INF 9 7       (5 는 더이상 의미없음, 7 은 INF 에 수신됨)
 *       INF 9 7 4                  (4 는 7 에 수신됨)
 *       INF 9 7 4 8 => INF 9 8     (7, 4 는 더이상 의미없음, 8 은 9 에 수신됨)
 *       -> 남은 INF 9 8 은 차례대로
 *          8 은 9 에 수신되고
 *          9 는 INF 에 수신된다
 *
 * - 가장 최근의 정보(탑의 높이)가 필요하다
 *   + Stack 을 사용하자!!!
 *     # push, pop 하면서 넣어주고 없애주면 되겠군
 *
 * Point
 * - 편의상 코드에서 스택에 들어가는 값들은 인덱스로 하였다
 *   + 답은 수신하는 탑의 높이가 아닌 인덱스 값이 필요하니까
 *
 * - 스택에 남겨진 값들은 탑의 높이 내림차순으로 정렬되어있다
 *   + 순회할 때마다 현재 다루고 있는 탑의 높이보다 작은 이전의 탑들의 인덱스들이 제거되기 때문에
 *
 * - 스택은 절대 empty 가 될 수 없다
 *   + 무한의 탑보다 큰 높이의 탑은 없으니까
 *     # 무한의 탑은 절대 pop 되지 않고 끝까지 남아있게 된다
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>
#include <stack>

using namespace std;

#define endl '\n'

// Set up : Global Variables
#define INF 987654321

// Set up : Functions Declaration
/* None */


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    int N; cin >> N;
    int T[N+1];
    for (int i=1; i<=N; i++) {
        cin >> T[i];
    } T[0] = INF; /* 무한의 탑 */

    // Process
    int A[N+1];
    stack<int> st; /* 스택에는 인덱스 값이 들어감 */
    st.push(0); /* 초기화 <= 무한의 탑을 넣어줌 */
    for (int i=1; i<=N; i++) {
        if (T[i] < T[st.top()]) { /* 현재 탑의 높이가 top 의 높이보다 작으면 */
            A[i] = st.top(); /* 현재 탑은 top 에 수신됨 */
            st.push(i); /* 스택에 현재 인덱스 추가 */
        } else {
            /* 현재 탑의 높이가 top 의 높이보다 크면 */
            while (T[i] > T[st.top()]) {
                st.pop(); /* 현재 탑의 높이가 top 의 높이보다 작아질 때까지 pop */
                /* 이 while 문에서 현재 탑의 높이보다 작은 이전의 값들이 제거됨 */
            } A[i] = st.top(); /* 현재 탑은 top 에 수신됨 */
            st.push(i); /* 스택에 현재 인덱스 추가 */
        }
    }

    /* 스택에 남은 인덱스 값들은 탑의 높이 내림차순으로 정렬되어있음 */
    /*   0 3 5 7 9 <= 현재 스택에 저장된 인덱스 값들
     * INF 8 6 4 2 <= 각 인덱스에 대응되는 탑의 높이
     * 라고 하면, 인덱스 기준
     * 9 는 7 에 수신됨
     * 7 은 5 에 수신됨
     * 5 는 3 에 수신됨
     * 3 은 0 에 수신됨 */
    while (true) {
        int curr = st.top(); /* 현재 탑  */
        st.pop();
        if (st.empty()) break; /* 이전 탑이 존재하지 않으면 while 문 종료 */
        /* 이전 탑이 존재하지 않는 경우는 curr=0, T[curr]=INF 일 때를 가리킴 */
        int prev = st.top(); /* 이전 탑 */
        A[curr] = prev; /* 현재 탑은 이전 탑에 수신됨 */
    }

    // Control : Output
    for (int i=1; i<=N; i++) {
        cout << A[i] << ' ';
    } cout << endl;
}

// Helper Functions
/* None */
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글