54 lines
1.9 KiB
Python
54 lines
1.9 KiB
Python
# 가잔 긴 증가하는 부분 수열
|
|
|
|
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]보다 큰 놈이 들어오면 그냥 뒤에 붙이면 된다.
|
|
이렇게 하면 원래 수열은 모르지만(복원하려면 따로 기록해야 한다.) 최대 길이를 알 수 있다.
|
|
""" |