// Subsir crescator maximal - complexitate O(NlogN), solutie cu arbori de intervale
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
int n, a[100010], A, B, val, X, Y, position, sol, pozsol;
bool ok;
int best[100010], pred[100010];
vector <int> vsol;
struct arbore
{
int minim, maxim, best, pos;
};
arbore aint[262150];
inline void Read()
{
freopen ("scmax.in", "r", stdin);
scanf ("%d\n", &n);
char ch[1100000];
int lg;
gets(ch);
lg = strlen(ch);
int i, nr = 0, x;
for(i=0; i<lg; i++)
{
x = 0;
while (i<lg && ch[i] >= '0' && ch[i] <= '9')
x = x*10 + (int)(ch[i] - '0'), i++;
a[++nr] = x;
}
}
inline void Build(int nod, int st, int dr)
{
if (st == dr)
{
aint[nod].minim = aint[nod].maxim = a[st];
aint[nod].best = 1;
aint[nod].pos = -1; // pos = pozitia in vectorul a in care se afla best
return ;
}
int mij, fiu;
mij = (st+dr)>>1;
fiu = nod<<1;
Build(fiu, st, mij);
Build(fiu+1, mij+1, dr);
aint[nod].minim = min(aint[fiu].minim, aint[fiu+1].minim);
aint[nod].maxim = max(aint[fiu].maxim, aint[fiu+1].maxim);
aint[nod].best = max(aint[fiu].best, aint[fiu+1].best);
if (aint[fiu].best > aint[fiu+1].best)
aint[nod].pos = aint[fiu].pos;
else
aint[nod].pos = aint[fiu+1].pos;
}
inline void Query(int nod, int st, int dr)
{
if (A <= st && dr <= B && aint[nod].maxim < val)
{
if (aint[nod].best > X)
{
X = aint[nod].best;
Y = aint[nod].pos;
ok = true;
}
return ;
}
int mij, fiu;
mij = (st+dr)>>1;
fiu = nod<<1;
if (A <= mij && aint[fiu].minim < val)
{
Query (fiu, st, mij);
}
if (mij < B && aint[fiu+1].minim < val)
{
Query (fiu+1, mij+1, dr);
}
}
inline void Update(int nod, int st, int dr)
{
if (st == dr)
{
aint[nod].best = val;
aint[nod].pos = st; // = position
return ;
}
int mij, fiu;
mij = (st+dr)>>1;
fiu = nod<<1;
if (position <= mij)
{
Update(fiu, st, mij);
}
else
{
Update(fiu+1, mij+1, dr);
}
if (aint[fiu].best > aint[fiu+1].best)
{
aint[nod].best = aint[fiu].best;
aint[nod].pos = aint[fiu].pos;
}
else
{
aint[nod].best = aint[fiu+1].best;
aint[nod].pos = aint[fiu+1].pos;
}
}
inline void Solve()
{
Build(1, 1, n);
int i;
for(i=1; i<=n; i++)
{
val = a[i];
A = 1;
B = i-1;
X = Y = 0;
ok = false;
Query(1, 1, n);
// returneaza in X maximul dintre best[1 ... i-1] cu proprietatea ca a[j] < a[i]
// si in Y pozitia in vectorul a la care se afla acest best;
if (ok == false)
Y = -1;
best[i] = X + 1;
pred[i] = Y;
if (best[i] > sol)
{
sol = best[i];
pozsol = i;
}
position = i;
val = X + 1;
Update(1, 1, n);
}
}
inline void Write()
{
freopen ("scmax.out", "w", stdout);
printf ("%d\n", sol);
do
{
vsol.push_back(a[pozsol]);
pozsol = pred[pozsol];
} while (pozsol != -1);
vector <int>::iterator it;
for (it = vsol.end()-1; it >= vsol.begin(); it--)
printf ("%d ", *it);
printf ("\n");
}
int main()
{
Read();
Solve();
Write();
return 0;
}