/// cu arbori de intervale
#include <fstream>
#include <algorithm>
using namespace std;
ifstream cin("scmax.in");
ofstream cout("scmax.out");
///LIS cu AINT
pair <int, int> v[100002], cp[100002];
int n, tree[400010];
int query(int node, int st, int dr, int left, int rigt) {
if (left <= st and dr <= rigt) {
return tree[node];
}
int mij = (st + dr) / 2, rez1 = 0, rez2 = 0;
if (left <= mij) {
rez1 = query(2*node, st, mij, left, rigt);
}
if (mij < rigt) {
rez2 = query(2*node+1, mij+1, dr, left, rigt);
}
return max(rez1, rez2);
}
void update(int node, int st, int dr, int pos, int val) {
if (st == dr and st == pos) {
tree[node] = val;
return ;
}
int mij = (st + dr)/2;
if (pos <= mij) {
update(2*node, st, mij, pos, val);
} else {
update(2*node+1, mij+1, dr, pos, val);
}
tree[node] = max(tree[2*node], tree[2*node+1]);
}
bool cmp(pair<int, int> a, pair<int, int> b) {
if (a.first == b.first)
return a.second > b.second;
return a.first < b.first;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> v[i].first;
cp[i].first = v[i].first;
v[i].second = i;
}
sort(v+1, v+n+1, cmp); /// sortam dupa valoare, retinand pozitia
int maxim = 0;
for (int i = 1; i <= n; i++) {
int nr = query(1, 1, n, 1, v[i].second);
update(1, 1, n, v[i].second, nr+1);
cp[v[i].second].second = nr+1;
}
cout << '\n';
cout << tree[1];
return 0;
}