Загрузка данных


#include <algorithm>
#include <iostream>
#include <vector>

namespace {
void computeDP(const std::vector<int>& vec,
               std::vector<int>& up,
               std::vector<int>& down) {
    const int size = static_cast<int>(vec.size());
    for (int i = size - 1; i >= 0; --i) {
        for (int j = i + 1; j < size; ++j) {
            if (vec[i] < vec[j]) {
                up[i] = std::max(up[i], down[j] + 1);
            } else if (vec[i] > vec[j]) {
                down[i] = std::max(down[i], up[j] + 1);
            }
        }
    }
}

int findLength(const std::vector<int>& up, const std::vector<int>& down) {
    int length = 0;
    for (int i = 0; i < up.size(); ++i) {
        length = std::max(length, up[i]);
        length = std::max(length, down[i]);
    }
    return length;
}

int findStart(const std::vector<int>& up,
              const std::vector<int>& down,
              int length) {
    int curr = 0;
    const int size = static_cast<int>(up.size());
    while (curr < size && up[curr] != length && down[curr] != length) {
        ++curr;
    }
    return curr;
}

int findNext(const std::vector<int>& vec,
             const std::vector<int>& up,
             const std::vector<int>& down,
             int curr,
             int rem,
             bool flag,
             bool reqUp,
             bool& chosen) {
    const int size = static_cast<int>(vec.size());
    for (int j = curr + 1; j < size; ++j) {
        if (vec[j] == vec[curr]) {
            continue;
        }
        const bool edgeUp = vec[j] > vec[curr];
        if (flag && edgeUp != reqUp) {
            continue;
        }
        const int sufx = edgeUp ? down[j] : up[j];
        if (sufx >= rem - 1) {
            chosen = edgeUp;
            return j;
        }
    }
    return -1;
}

std::vector<int> buildAnswer(const std::vector<int>& vec,
                             const std::vector<int>& up,
                             const std::vector<int>& down,
                             int length) {
    std::vector<int> ans;
    ans.reserve(length);

    int curr = findStart(up, down, length);
    ans.push_back(vec[curr]);

    int rem = length;
    bool flag = false;
    bool reqUp = false;

    while (rem > 1) {
        bool chosen = false;
        const int nxt = findNext(vec, up, down, curr, rem, flag, reqUp, chosen);
        curr = nxt;
        ans.push_back(vec[curr]);
        --rem;
        reqUp = !chosen;
        flag = true;
    }
    return ans;
}

void printAnswer(const std::vector<int>& ans) {
    for (int i = 0; i < ans.size(); ++i) {
        if (i > 0) {
            std::cout << ' ';
        }
        std::cout << ans[i];
    }
    std::cout << '\n';
}

}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int size = 0;
    std::cin >> size;

    std::vector<int> vec(size);
    for (int i = 0; i < size; ++i) {
        std::cin >> vec[i];
    }

    std::vector<int> up(size, 1);
    std::vector<int> down(size, 1);

    computeDP(vec, up, down);
    const int length = findLength(up, down);
    const std::vector<int> ans = buildAnswer(vec, up, down, length);

    printAnswer(ans);
    return 0;
}