// B3637 最长上升子序列 !important
// 线性动态规划 O(nlogn)
#include <bits/stdc++.h>
using namespace std;
const int MAXn = 1e4 + 9;
int d[MAXn], dp[MAXn], h[MAXn];
int main() {
for(int i = 1; i <= MAXn - 3; i ++)
h[i] = INT_MAX; // 下降:h[i] = INT_MIN;
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%d", &d[i]);
int m = 0;
for(int i = 1; i <= n; i ++) {
dp[i] = 1; // 一定包含自己的以自己结尾的最长XX子序列长度
// 波式二分,在 h 数组中二分找到小于/大于[等于]要二分的 d[i] 的值
int p = 0;
for(int j = 20; j >= 0; j --) {
int pp = p | (1 << j);
if(pp <= m && h[pp] < d[i]) p = pp; // 下降:h[pp] > d[i]
}
dp[i] = p + 1; // 二分出的 dp[i] 的值
m = max(m, dp[i]); // 最长的序列值,也是 h 数组的最后一位
h[dp[i]] = min(h[dp[i]], d[i]); // 下降:max(h[dp[i]], d[i])
// h[i]: 长度为 i 的序列的最后一位的最小/大值,升 min 降 max
}
// int ans = 0;
// for(int i = 1; i <= n; i ++)
// ans = max(ans, dp[i]);
printf("%d", m);
return 0;
}