#include <fstream>
#include <iostream>
#include <algorithm>
#include <set>
#include <cstdlib>
using namespace std;
const int VMAX = 100001;
int v[VMAX];
int best[VMAX];
int arbore[4 * VMAX];
set<int> all;
int allV[VMAX], dv = 0;
int compareints (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
void update(int pos, int valoare, int nod, int st, int dr) {
if (pos < st || pos > dr) return;
if (dr < st) return;
arbore[nod] = max(arbore[nod],valoare);
if (st == dr) return;
int mijloc = (st + dr) / 2;
update(pos, valoare, nod * 2, st, mijloc);
update(pos, valoare, nod * 2 + 1, mijloc + 1, dr);
}
int query(int l, int r, int nod, int st, int dr) {
if (dr < st) return -1;
if (r < st) return -1;
if (l > dr) return -1;
if (l <= st && r >= dr) return arbore[nod];
int mijloc = (st + dr) / 2;
return max(query(l, r, nod * 2, st, mijloc), query(l, r, nod * 2 + 1, mijloc + 1, dr));
}
int main() {
ifstream fin("scmax.in");
ofstream fout("scmax.out");
int n;
fin>>n;
for (int i = 0; i < n; ++i) {
fin>>v[i];
all.insert(v[i]);
}
for (set<int>::iterator it = all.begin(); it != all.end(); ++it) {
allV[dv++] = *it;
}
for (int i = 0; i < n; ++i) {
v[i] = (int*) bsearch (v + i, allV, dv, sizeof (int), compareints) - allV;
// cout<<v[i]<<" ";
}
int solutie = 0;
for (int i = 0; i < n; ++i) {
int mx = 1;
if (v[i] > 0)
mx += query(0, v[i] - 1, 1, 0, n);
update(v[i], mx, 1, 0, n);
solutie = max(solutie, mx);
}
fout<<solutie;
// cout<<solutie;
fout.close();
return 0;
}