학습 내용/백준 문제풀이

백준 14003 파이썬 - 가장 긴 증가하는 부분 수열 5

ohksj77 2022. 3. 23. 23:59

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

 

14003번: 가장 긴 증가하는 부분 수열 5

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (-1,000,000,000 ≤ Ai ≤ 1,000,000,000)

www.acmicpc.net

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {1020, 10, 30, 20, 50} 이고, 길이는 4이다.

코드

import sys
from bisect import bisect_left
length = int(sys.stdin.readline())
arr = [0] + list(map(int, sys.stdin.readline().split()))
dp = [0 for _ in range(length + 1)]
compare = [-1000000001]
maxNum = 0
for i in range(1, length + 1):
    if compare[-1] < arr[i]:
        compare.append(arr[i])
        dp[i] = len(compare) - 1
        maxNum = dp[i]
    else:
        dp[i] = bisect_left(compare, arr[i])
        compare[dp[i]] = arr[i]
print(maxNum)
result = []
for i in range(length, 0, -1):
    if dp[i] == maxNum:
        result.append(arr[i])
        maxNum -= 1
print(*(reversed(result)))

풀이

비슷한 다른 문제가 있지만 여기는 수의 범위가 커서 다른 방식으로 풀어야 했다.

메모이제이션을 통해 dp로 풀지만, 바이너리 서치가 합쳐진 형태이다. 이진 탐색은 compare리스트를 만들어 실행한다. 현재 배열 값이 이진 탐색 리스트의 가장 큰 값보다 크면 가장 긴 수열이 갱신되는 것이다. 만약 그렇지 않다면 현재 배열 값이 이진 탐색 리스트의 어디에 해당하는지 비교해서 값을 넣는다.