"""
基本思想:
1. 状态表示:
1.1 集合f[i]:以序列中以第i个数结尾的所有上升子序列集合
1.2 属性:max,即以第i个数结尾的所有上升子序列的长度的最大值
2. 状态计算(状态转移方程, 根据以第i个数结尾的所有上升子序列的倒数第二个数的位置进行集合划分,其中f[i]是倒数第一个数):
f[i]=1 !!!注意,容易出错
f[i] = max{f[i], f[j+1]}, j=0,1,2,...,i-1; and f[j]<f[i]
输入示例:
7
3 1 2 1 8 5 6
输出样例:
4
"""
# 不记录最长子序列
# 输入示例
n = int(input().strip())
nums = [0]
nums.extend(list(map(int, input().split())))
# 初始化dp数组
dp = [0 for i in range(n+1)]
# 不记录子序列元素
for i in range(1,n+1):
dp[i] = 1
for j in range(1,i):
# dp[i] = 1 !!! 注意,出错了,初始化dp[i]不能放在内循环里,否则在执行内循环时dp[i]会不断初始化为1
if nums[j]<nums[i]:
dp[i] = max(dp[i], dp[j]+1) # 状态转移方程
res = 0
for i in range(n+1):
res = max(res, dp[i])
print(res)
#记录子序列元素
# 初始化dp数组
dp = [0 for i in range(n+1)]
pathIndex = [0] # 填0补位,使第一个数在第1个位置。pathIndex用来存储存储dp数组中第i个元素是由哪个元素得到的(可能是第i个元素本身,也可能是某个元素加1)
for i in range(1,n+1): #1-7
dp[i] = 1
pathIndex.append(0)
for j in range(1,i):
# dp[i] = 1 !!! 注意,出错了,初始化dp[i]不能放在内循环里,否则在执行内循环时dp[i]会不断初始化为1
if nums[j]<nums[i]:
if dp[j]+1>dp[i]:
dp[i] = dp[j]+1 # 状态转移方程
pathIndex[-1] = j # !!!出错:这里是标记第i个位置是由第j个位置加1得到的,而不能写成pathIndex[-1] = i
k = 0 # 记录最大长度元素的下标
for i in range(n+1): # 找到dp数组中最大值的索引,赋值为k
if dp[i]>dp[k]:
k = i
# print(k, dp[k]) # 7 4, 其中dp[k]表示最长子序列的长度
for i in range(dp[k]):
print(nums[k], end=' ')
k = pathIndex[k]