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