#include <iostream>
#include <stdio.h>
#include <unordered_map>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
#define point pair<int32_t, int32_t>
#define mmap unordered_map<int32_t, int32_t>
unordered_map<uint64_t, int32_t> arb;
uint64_t getIndex(int32_t x, int32_t y) {
return (uint64_t)x * 100000ULL + (uint64_t)y;
}
void add(int32_t *sets, int32_t value, int32_t pos, int32_t left, int32_t right, int32_t n) {
if(pos < left || pos > right) {
return ;
}
if(left == right && left == pos) {
sets[pos] = value;
arb[getIndex(left, right)] = value;
return ;
}
int32_t m = (left + right) / 2;
add(sets, value, pos, left, m, n);
add(sets, value, pos, m + 1, right, n);
if(left <= pos && right >= pos) {
//sets[getIndex(left, right, n)] = max(sets[getIndex(left, m, n)], sets[getIndex(m + 1, right, n)]);
arb[getIndex(left, right)] = max(arb[getIndex(left, m)], arb[getIndex(m + 1, right)]);
}
}
void addIntervalTree(int32_t *sets, int32_t value, int32_t pos, int32_t n) {
add(sets, value, pos, 0, n - 1, n);
}
int32_t getMax_t(int32_t *sets, int32_t n, int32_t left, int32_t right, int32_t iniLeft, int32_t iniRight) {
if(left >= iniLeft && right <= iniRight) {
//return sets[getIndex(left, right, n)];
return arb[getIndex(left, right)];
}
if((left < iniLeft && right < iniLeft) || (right > iniRight && left > iniRight)) {
return 0;
}
int32_t m = (left + right) / 2;
int32_t leftMax = getMax_t(sets, n, left, m, iniLeft, iniRight);
int32_t rightMax = getMax_t(sets, n, m + 1, right, iniLeft, iniRight);
return max(rightMax, leftMax);
}
int32_t getMax(int32_t *sets, int32_t n, int32_t left, int32_t right) {
if(left >= right) {
return sets[left];
}
return getMax_t(sets, n, 0, n - 1, left, right);
}
void rebuild(FILE *fr, int32_t *trueSets, int32_t *buffer, int32_t index, mmap &indexes) {
int32_t currentValue = buffer[indexes[trueSets[index]]];
vector<int32_t> art;
art.push_back(trueSets[index]);
while(currentValue != 1 && index >= 0) {
int32_t newIndex = indexes[trueSets[index]];
if(buffer[newIndex] + 1 == currentValue) {
art.push_back(trueSets[index]);
currentValue--;
}
index--;
}
for(int32_t i = art.size() - 1; i >= 0; i--) {
fprintf(fr, "%d ", art[i]);
}
}
int main() {
FILE *fd = fopen("scmax.in", "r+");
FILE *fr = fopen("scmax.out", "w+");
int32_t n, *buffer = (int32_t *)malloc(sizeof(int32_t) * 440004);
memset(buffer, 0, sizeof(int32_t) * 440004);
int32_t *sets = (int32_t *)malloc(sizeof(int32_t) * 100004), *trueSets = (int32_t *)malloc(sizeof(int32_t) * 100004);
fscanf(fd, "%d", &n);
mmap indexes;
for(int32_t i = 0; i < n; i++) {
fscanf(fd, "%d", &sets[i]);
trueSets[i] = sets[i];
}
sort(sets, sets + n);
for(int32_t i = 0; i < n; i++) {
indexes[sets[i]] = i;
}
int32_t totalMax = 1, finalIndex = 0;
for(int32_t i = 0; i < n; i++) {
int32_t newIndex = indexes[trueSets[i]];
int32_t maxElement = getMax(buffer, n, 0, newIndex - 1) + 1;
if(totalMax < maxElement) {
finalIndex = i;
totalMax = maxElement;
}
addIntervalTree(buffer, maxElement, newIndex, n);
}
fprintf(fr, "%d\n", totalMax);
rebuild(fr, trueSets, buffer, finalIndex, indexes);
}