#include<stdio.h>
#include<math.h>
FILE *f,*g;
long T[100000],B[100000],arbb,A[100000],n,i,maximum,P[100000],m,s1,s2,p,arb[250000],lim1[250000],lim2[250000],poz,c[100000];
long tm(long i)
{ long nr=0;
while(i%2==0) { nr++; i/=2; }
return nr;
}
void msort(long a,long b)
{ long i,j,k,m;
if(a==b) return;
m=(a+b)/2;
msort(a,m); msort(m+1,b);
for(i=1;i<=b;i++) T[i]=B[i];
for(i=k=a,j=m+1;i<=m&&j<=b;)
if(A[T[i]]<A[T[j]]) B[k++]=T[i++];
else B[k++]=T[j++];
while(i<=m) B[k++]=T[i++];
while(j<=b) B[k++]=T[j++];
}
long cautare(long x,long a,long b)
{ m=(a+b)/2;
if(P[m]==x) return m;
else if(x>P[m]) return cautare(x,m+1,b); else return cautare(x,a,m-1);
}
long maxx(long a,long b) { if(a>b) return a; return b; }
long querry(long nod,long x,long y)
{ long mij=(lim1[nod]+lim2[nod])/2;
if(x>y) return 0;
else if(x>lim2[nod]||y<lim1[nod]) return 0;
else if(lim2[nod]==lim1[nod]) return arb[nod];
else
{ if(x<=mij&&y<=mij) return querry (2*nod,x,y);
else if(x>mij) return querry(2*nod+1,x,y);
return maxx(querry(2*nod+1,x,y),querry(2*nod,x,y));
}
}
void update(long nod,long x,long y)
{ long mij=(lim1[nod]+lim2[nod])/2;
if(lim1[nod]==lim2[nod]&&lim1[nod]==x) arb[nod]=y;
else if(x>=lim1[nod]&&x<=lim2[nod])
{ if(x<=mij) update(2*nod,x,y); else update(2*nod+1,x,y);
arb[nod]=maxx(arb[2*nod],arb[2*nod+1]);
}
}
int main()
{ f=fopen("scmax.in","r"); g=fopen("scmax.out","w");
fscanf(f,"%ld",&n);
for(i=1;i<=n;i++) { fscanf(f,"%ld",&A[i]); B[i]=i; }
lim1[1]=1; lim2[1]=n;
for(i=1;i<=n;i++)
{ lim1[2*i]=lim1[i]; lim2[2*i]=(lim1[i]+lim2[i])/2;
lim1[2*i+1]=(lim1[i]+lim2[i])/2+1; lim2[2*i+1]=lim2[i];
}
msort(1,n); for(i=1;i<=n;i++) P[i]=A[B[i]];
maximum=0;
for(i=n;i>=1;i--)
{ poz=cautare(A[i],1,n);
arbb=1+querry(1,poz+1,n);
update(1,i,arbb); c[i]=arbb; if(c[i]>maximum) maximum=c[i];
}
fprintf(g,"%ld",maximum); fclose(g);
return 0;
}