#include <iostream>
#include <fstream>
#define nmax 100006
using namespace std;
const char iname[] = "scmax.in";
const char oname[] = "scmax.out";
ifstream fin(iname);
ofstream fout(oname);
int N, i, j, k, dp[nmax], pred[nmax], rez, poz[nmax * 4], rasp[nmax * 4], maxim, max2, A[nmax], B[nmax];
int position, max3, val;
struct nod { int v, poz;};nod aux[nmax];
struct cmp
{
bool operator()(const nod &a, const nod &b)const
{
if(a.v < b.v)
return 1;
return 0;
}
};
void update(int nod, int left, int right, int valoare, int pozitie)
{
if(left == right)
{
rasp[nod] = dp[pozitie];
poz[nod] = pozitie;
return;
}
int middle = (left + right) >> 1;
if(valoare <= middle)
update(2 * nod, left, middle, valoare, pozitie);
else
update(2 * nod + 1, middle + 1, right, valoare, pozitie);
rasp[nod] = max(rasp[2 * nod + 1], rasp[2 * nod]);
if(rasp[2 * nod + 1] == rasp[nod])
poz[nod] = poz[2 * nod + 1];
else
poz[nod] = poz[2 * nod];
}
void query(int nod, int left, int right, int lm, int rm)
{
if(lm <= left && right <= rm)
{
if(rasp[nod] >= max2)
{
max2 = rasp[nod];
max3 = poz[nod];
return;
}
else
return;
}
int middle = (left + right) >> 1;
if(lm <= middle)
query(2 * nod, left, middle, lm, rm);
if(middle < rm)
query(2 * nod + 1, middle +1 , right, lm, rm);
}
int main()
{
fin >> N;
for(i = 1; i <= N; i ++)
{
fin >> A[i];
aux[i].v = A[i];
aux[i].poz = i;
}
dp[1] = 1;
pred[1] = 1;
memcpy(B, A, sizeof(A));
j = 1;
sort(aux + 1, aux + N + 1, cmp());
B[aux[1].poz] = ++j;
for(i = 2; i <= N; i ++)
{
if(aux[i].v != aux[i - 1].v)
B[aux[i].poz] = ++j;
else
B[aux[i].poz] = j;
}
for(i = 1; i <= N; i ++)
{
if(B[i] > maxim)
maxim = B[i];
}
update(1, 1, maxim, B[1], 1);
for(i = 2; i <= N; i ++)
{
max2 = 0;
query(1, 1, maxim, 1, B[i] - 1);
dp[i] = max(dp[i], dp[max3] + 1);
update(1, 1, maxim, B[i], i);
}
max2 = 0;
for(i = 1; i <= N; i ++)
if(dp[i] > max2)
max2 = dp[i];
fout << max2;
return 0;
}