본문 바로가기

Algorithm & Data Structure

백준 - 2493번(스택)

728x90
반응형

https://www.acmicpc.net/problem/2493

 

2493번: 탑

첫째 줄에 탑의 수를 나타내는 정수 N이 주어진다. N은 1 이상 500,000 이하이다. 둘째 줄에는 N개의 탑들의 높이가 직선상에 놓인 순서대로 하나의 빈칸을 사이에 두고 주어진다. 탑들의 높이는 1

www.acmicpc.net

 

import sys

n = int(sys.stdin.readline())

arr = list(map(int,sys.stdin.readline().split()))
ans = [0 for _ in range(n)]

tmp = [[arr.pop(),len(arr)+1]] #가장 오른쪽에 있는 값, 해당 값이 몇번째 탑인지

while len(arr) > 0:
    t = arr.pop()
    if t >= tmp[0][0]:
        #해당 시점에 tmp안에 원소들은 전부 t에서 수신 받는다.
        while tmp:
            x = tmp.pop()
            ans[x[1] - 1] = len(arr) + 1
        tmp.append([t, len(arr) + 1])

    elif t >= tmp[-1][0]:
        while tmp:
            x = tmp.pop()
            if t >= x[0]:
                #t보다 작거나 같은 원소는 t에서 수신 받는다.
                ans[x[1] - 1] = len(arr) + 1
            else:
                #t보다 큰 원소가 존재하면 tmp에 다시 t를 넣어주고 종료
                tmp.append(x)
                break
        tmp.append([t, len(arr) + 1])
    else:
        tmp.append([t, len(arr) + 1])

print(*ans)

코드가 길진 않지만 아이디어가 생각보다 복잡했다.

탑의 끝쪽부터 탐색해야 하는 문제라서 reverse() 함수 같은걸 사용할 생각 하면 절대 안 된다.

탑의 수가 굉장히 많고 탑들의 높이로 주어지는 범위도 굉장히 크기 때문에 시간 초과가 날것이다.

arr.pop()을 해주면 O(1)의 시간 복잡도로 가장 마지막에 있는 원소부터 꺼낼 수 있다.

기본적인 원리는 다음과 같다.

만약에 이번에 꺼낸 탑의 높이가 처음으로 꺼낸 탑의 높이(즉, tmp[0][0]) 보다 크거나 같으면 tmp에 들어 있는 애들을 전부 인덱스에 맞게 넣어준다. 이유는 tmp에 들어있는 애들은 tmp[0][0] 보다 작은 애들만 들어 있기 때문이다.

그러나 만약에 t가 tmp[0][0] 보다는 작은데 최근에 넣은 tmp값 보다 큰 경우가 생길 거다. 예를 들어 6 5 7 이런 경우 말이다.

그럴 땐 t보다 작거나 같은 원소는 ans에 인덱스를 대입해 주면서 조건에 맞는 원소들을 제거해준다.

그렇지 않은 원소를 만나면 반복문을 탈출하고 tmp에 t를 대입해준다.

ans에 인덱스를 조금 편하게 대입하기 위해서 2차원 리스트를 이용해서 x [i][1]을 호출해주면 된다.

tmp가 증가할 때마다 arr은 줄어드는 부분을 생각해 보면 된다.

최종적으로 ans를 출력해주면 답이 나온다.

 

728x90
반응형

'Algorithm & Data Structure' 카테고리의 다른 글

백준 - 1004번(기하)  (0) 2022.03.31
백준 - 9935번(스택)  (0) 2022.03.31
백준 - 10828번(스택)  (0) 2022.03.31
백준 - 17608번(스택)  (0) 2022.03.31
백준 - 1012번(DFS,BFS 문제지만 완전 탐색으로 품)  (0) 2022.02.23