백준 12015 [python]

김석·2022년 2월 1일
0

백준

목록 보기
5/13

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

import sys

def binary_search(start, end, a):
    global res
    if start > end:
        return
    mid = (end + start) // 2
    
    if stk[mid] < a: 
        binary_search(mid + 1, end, a)
    elif stk[mid] > a:
        res = mid
        binary_search(start, mid - 1, a)
    else:
        res = mid
        return

n = int(input())
a_list = list(map(int, sys.stdin.readline().split()))
res = 0
stk = [0]

for a in a_list:
    if stk[-1] < a:
        stk.append(a)
    else:
        binary_search(1, len(stk) - 1, a)
        stk[res] = a
print(len(stk) - 1)

나무위키의 도움을 받았다.
https://namu.wiki/w/%EC%B5%9C%EC%9E%A5%20%EC%A6%9D%EA%B0%80%20%EB%B6%80%EB%B6%84%20%EC%88%98%EC%97%B4

알고리즘은 단순하게 스택 맨 위 원소와 숫자를 비교해서 크면 스택에 넣고, 작으면 스택의 원소 중 본인보다 큰 수들 중 가장 작은 원소에 대입한다. 그 과정에서 이분 탐색이 쓰인다.

이 알고리즘이 왜 항상 예외 없이 정답을 도출하는지 생각하는게 조금 어려웠다. 작은 놈이 스택에 적당한 위치에 치환되는 과정에서는 당연하게 손해보지 않는다. 나중에 방금 치환한 원소를 포함한 LIS가 등장할 수 있기 때문이다. 그렇지만 원소를 치환하는 과정에서 스택의 길이는 짧아지지 않으니 이미 만들어진 LIS의 길이는 보험이 깔려있다.

하지만 길이에만 보험이 깔려있을 뿐 그 뒤에 나오는 수들이 쌓이면서 만들어진 스택은 LIS일 수도, 뒤죽박죽 섞인 수열일 수도 있기 때문에 LIS를 구하려면 다른 방법도 써야 한다.

profile
handsome

0개의 댓글

관련 채용 정보