코테/BOJ

백준 12015 [가장 긴 증가하는 부분 수열 2] 파이썬

동 캄 2025. 6. 15. 14:37
반응형

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

 

#백준 12015 가장 긴 증가하는 부분 수열 2
from collections import defaultdict
N=int(input())
arr=list(map(int,input().split()))

dp=[0 for _ in range(N+1)]
dp[0]=1
dic=defaultdict()
dic[arr[0]]=1
is_changed=False
for i in range(1,N):
    for val in dic:
        if val<arr[i]:
            dp[i]=max(dp[i],dic[val])
            is_changed=True
    if is_changed:
        dp[i]+=1
        dic[arr[i]]=dp[i]
        is_changed=False
    else:
        dp[i]=1
        dic[arr[i]]=1
print(max(dp))

O(N^2) 복잡도로 해결하려고 하였는데 실패하였다. 이 문제는 이분탐색을 이용하여야만 풀 수 있는 문제였다.

 

결국 해결하지 못해서, GPT의 도움을 받았다.

 

#백준 12015 가장 긴 증가하는 부분 수열 2
import sys
from bisect import bisect_left

# 입력 받기
N = int(sys.stdin.readline())
arr = list(map(int, sys.stdin.readline().split()))

# tails 리스트 초기화
# tails[k]는 길이가 k+1인 증가 부분 수열의 가장 작은 마지막 원소를 저장합니다.
tails = []

for num in arr:
    # bisect_left를 사용하여 num이 tails에 들어갈 적절한 위치(인덱스)를 찾습니다.
    # 이 위치는 num보다 크거나 같은 첫 번째 원소의 인덱스입니다.
    idx = bisect_left(tails, num)

    if idx == len(tails):
        # 만약 idx가 tails의 길이와 같다면,
        # 이는 num이 tails의 모든 원소보다 크다는 의미입니다.
        # 따라서 num은 기존의 가장 긴 증가 부분 수열보다 더 긴 수열을 만듭니다.
        # num을 tails의 끝에 추가합니다.
        tails.append(num)
    else:
        # 그렇지 않다면, num은 tails[idx]의 위치에 들어갈 수 있습니다.
        # 이는 길이가 (idx + 1)인 증가 부분 수열을 만들 수 있음을 의미하며,
        # tails[idx]를 num으로 교체함으로써 같은 길이의 수열 중
        # 더 작은 마지막 원소를 가지는 '더 좋은' 수열을 만들 수 있습니다.
        # 이렇게 되면 나중에 오는 숫자들은 이 더 작은 마지막 원소에 더 쉽게 연결될 수 있습니다.
        tails[idx] = num

# tails 리스트의 길이가 최장 증가 부분 수열의 길이입니다.
print(len(tails))

갈 길이 멀다..

반응형