수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다.
둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)
첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.
예제입력
6
10 20 10 30 20 50
예제출력
4
from bisect import bisect_left
n=int(input())
a=list(map(int,input().split()))
d=[a[0]]
for x in a:
if d[-1]<x:
d.append(x)
else:
# ex) 1,5,200,10과 같은 경우 x=10일때 d=[1,5,200]이고
# 이때 200자리에 10이 대신 들어가야한다.
# 길이를 구하는것이므로 d안의 수는 상관없음
d[bisect_left(d,x)]=x
print(len(d))
가장 긴 증가하는 부분 수열과 동일하지만 조건이 1,000,000로 늘어났으므로 DP로 풀경우 시간초과O(N^2)
이분탐색을 이용하면 O(NlogN)이므로 통과한다.
이분탐색의 경우, bisect 라이브러리를 사용하면 쉽게 구할 수 있다.
이진 검색 알고리즘을 이용해서 시퀀스를 검색하고, 시퀀스에 항목을 삽입할수 있는 함수를 제공한다.
bisect_right()는 x와 동일한 값이 시퀀스 a에 존재할 때 x와 동일한 값 바로 뒤 위치를 리턴한다.
반면에 bisect_left()는 x와 동일한 값 위치를 리턴한다.