11053-s2 성공

This commit is contained in:
sm4640
2026-03-27 17:34:41 +09:00
parent 3222e78317
commit a1c9fe6798

View File

@@ -0,0 +1,54 @@
# 가잔 긴 증가하는 부분 수열
import sys
input = sys.stdin.readline
def binary_search(target, lis):
l, r = 0, len(lis)
while l < r:
mid = (l+r)//2
if lis[mid] >= target:
r = mid
else:
l = mid + 1
return l
def solution():
n = int(input().rstrip())
lst = list(map(int, input().rstrip().split()))
lis = []
for k in lst:
if not lis or k > lis[-1]:
lis.append(k)
continue
lis[binary_search(k, lis)] = k
print(len(lis))
return
solution()
"""
걸린 시간: 10분
시간 복잡도: 내 풀이는 모든 수를 보는데 그 수가 lis에서 들어갈 자리를 이분탐색으로 확인하기 때문에 O(nlogn)이다.
해설: 원래는 11055(가장 큰 증가하는 부분수열)번처럼 하나의 수를 볼때 앞에 나온 수중에 본인보다 작은 수의 dp 값을 보고 거기에 +1한 값의 최대가
본인을 포함한 증가하는 수열의 길이이다. 근데 이것도 O(n^2)이다.
따라서 나는 길이만 알면 되기 때문에 좀 더 시간을 줄여보았다.
각 숫자를 순서대로 보면서 lis라는 리스트에 최대한 작은 수들을 넣는 것이다.
예를 들어, [1, 5, 8] 이렇게 있을 때, 지금 보는 수가 3이라면 5대신 3으로 바꿔끼면 된다.
이렇게 되면 3이 나중에 나온건데, 8이 아직도 있으니까 헷갈릴 수 있다.
하지만 이건 lis[i]를 i개의 길이에서 가장 작은 녀석이라고 생각하면 된다.
그럼 lis[2]는 2개짜리 수열 중에 제일 큰 놈의 최소가 3으로 됐을 뿐이고, lis[3]은 3개짜리 수열 중에 제일 큰 놈의 최소가 8일 뿐이다.
이렇게 진행을 하고 lis[-1]보다 큰 놈이 들어오면 그냥 뒤에 붙이면 된다.
이렇게 하면 원래 수열은 모르지만(복원하려면 따로 기록해야 한다.) 최대 길이를 알 수 있다.
"""