# 가장 긴 증가하는 부분 수열 4 import sys input = sys.stdin.readline def binary_search(result, target): l, r = 0, len(result)-1 idx = len(result) while l <= r: mid = (l+r)//2 if result[mid][0] >= target: idx = mid r = mid - 1 else: l = mid + 1 return idx def solution(): n = int(input().rstrip()) lst = list(map(int, input().rstrip().split())) parent = [-1] * (n) result = [(lst[0], 0)] for i in range(1, n): if lst[i] > result[-1][0]: parent[i] = result[-1][1] result.append((lst[i], i)) continue idx = binary_search(result, lst[i]) if result[idx][0] != lst[i]: result[idx] = (lst[i], i) if idx != 0: parent[i] = result[idx-1][1] answer = [result[-1][0]] parent_idx = parent[result[-1][1]] while parent_idx != -1: answer.append(lst[parent_idx]) parent_idx = parent[parent_idx] print(len(answer)) print(*answer[::-1]) return solution() """ 걸린 시간: 39분 시간 복잡도: 하나의 수에 대해. 이진탐색을 진행하기 때문에 O(nlogn)이다. 해설: 가장 긴 증가하는 부분 수열 문제에서 수열 자체를 알아야 하는 문제이다. 기존에 하던 방식은 개수만 원했기 때문에 결과 리스트에 업데이트 하면서 진행했다. 하지만 결과 리스트에 있는 것들은 그것 자체가 수열이 아니고, result[i]는 i개의 증가하는 수열들의 맨 뒤 값 중 가장 작은 값이다. 따라서 result를 업데이트 하면서 현재 보는 수의 바로 이전 수를 기록해놔야 한다.(parent 기록) 바로 이전 수는 result에서 binary_search를 했을 때, 본인이 들어갈 idx의 앞에 있는 수가 내가 맨 뒤일때 최선의 수이다. 따라서 그 수의 idx를 계속 기록하면 된다. 마지막에 result[-1]의 parent를 계속 역추적 하면 하나의 수열이 완성된다. """