#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int NMAX = 100000;
const int TMAX = 1 << 18;
const int MINF = 0;
int Tree[TMAX], Id[NMAX], A[NMAX], ans = 0, n;
vector<pair<int, int> > Manip;
inline int left(int i) {
return 2 * i;
}
inline int right(int i) {
return 2 * i + 1;
}
void buildTree(int i, int l, int r) {
if (l == r) {
Tree[i] = MINF;
return;
}
int m = (r - l) / 2 + l;
buildTree(left(i), l, m);
buildTree(right(i), m + 1, r);
Tree[i] = max(Tree[left(i)], Tree[right(i)]);
}
int queryTree(int lt, int rt, int i, int l, int r) {
if (lt <= l && r <= rt)
return Tree[i];
int m = (r - l) / 2 + l, ansl = MINF, ansr = MINF;
if (lt <= m)
ansl = queryTree(lt, rt, left(i), l, m);
if (m < rt)
ansr = queryTree(lt, rt, right(i), m + 1, r);
return max(ansl, ansr);
}
void updateTree(const int pos, int i, int l, int r) {
int q;
if (l == r && l == Id[pos]) {
if (Id[pos] > 1)
q = queryTree(1, Id[pos] - 1, 1, 1, n);
else
q = 0;
Tree[i] = max(q + 1, 1);
ans = max(ans, Tree[i]);
return;
}
int m = (r - l) / 2 + l;
if (Id[pos] <= m)
updateTree(pos, left(i), l, m);
else
updateTree(pos, right(i), m + 1, r);
Tree[i] = max(Tree[left(i)], Tree[right(i)]);
}
int main() {
freopen("scmax.in", "r", stdin);
freopen("scmax.out", "w", stdout);
scanf("%d", &n);
int i;
for (i = 0; i < n; ++ i) {
scanf("%d ", &A[i]);
Manip.push_back(make_pair(A[i], i));
}
sort(Manip.begin(), Manip.end());
int id = 1;
for (i = 0; i < n; ) {
do {
Id[Manip[i].second] = id;
++ i;
} while (i < n && Manip[i].first == Manip[i - 1].first);
++ id;
}
buildTree(1, 1, n);
for (i = 0; i < n; ++ i)
updateTree(i, 1, 1, n);
printf("%d\n", ans);
return 0;
}