Cod sursa(job #3365647)

Utilizator CatPanCatalin Pangaleanu CatPan Data 23 septembrie 2026 03:10:02
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.07 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

std::pair<int, int> querySegTree(const std::vector<std::pair<int, int>>& segTree, const std::vector<int>& values,
                                 int node, int treeLeft, int treeRight, int left, int right)
{
    if (right < treeLeft || left > treeRight)
    {
        return {0, -1};
    }

    if (left <= treeLeft && right >= treeRight)
    {
        return segTree[node];
    }

    int treeMid = (treeLeft + treeRight) / 2;

    return std::max(querySegTree(segTree, values, 2 * node + 1, treeLeft, treeMid, left, right),
                    querySegTree(segTree, values, 2 * node + 2, treeMid + 1, treeRight, left, right));
}

void updateSegTree(std::vector<std::pair<int, int>>& segTree, const std::vector<int>& values,
                   int node, int treeLeft, int treeRight, int position, const std::pair<int, int>& newValue)
{
    if (treeLeft == treeRight)
    {
        segTree[node] = newValue;
        return;
    }

    int treeMid = (treeLeft + treeRight) / 2;

    if (position <= treeMid)
    {
        updateSegTree(segTree, values, 2 * node + 1, treeLeft, treeMid, position, newValue);
    }
    else
    {
        updateSegTree(segTree, values, 2 * node + 2, treeMid + 1, treeRight, position, newValue);
    }

    segTree[node] = std::max(segTree[2 * node + 1], segTree[2 * node + 2]);
}

int main()
{
    std::ifstream fin("scmax.in");

    int n;
    fin >> n;

    std::vector<int> numbers(n);
    for (int i = 0; i < n; ++i)
    {
        fin >> numbers[i];
    }

    fin.close();

    std::vector<int> sortedIndexes(n);
    std::iota(sortedIndexes.begin(), sortedIndexes.end(), 0);
    std::sort(sortedIndexes.begin(), sortedIndexes.end(), [refNumbers = std::cref(numbers)](int a, int b){
        return refNumbers.get()[a] < refNumbers.get()[b] || (refNumbers.get()[a] == refNumbers.get()[b] && a > b);
    });

    std::vector<int> indexAfterSort(n);
    for (int i = 0; i < n; ++i)
    {
        indexAfterSort[sortedIndexes[i]] = i;
    }

    std::vector<int> bestLen(n), previous(n, -1);
    std::vector<std::pair<int, int>> segTree(4 * n, {0, -1});
    for (int i = 0; i < n; ++i)
    {
        std::pair<int, int> result = querySegTree(segTree, bestLen, 0, 0, n - 1, 0, indexAfterSort[i] - 1);
        bestLen[indexAfterSort[i]] = result.first + 1;
        updateSegTree(segTree, bestLen, 0, 0, n - 1, indexAfterSort[i], {bestLen[indexAfterSort[i]], indexAfterSort[i]});
        previous[indexAfterSort[i]] = result.second;
    }

    std::ofstream fout("scmax.out");

    int ansIndex = std::max_element(bestLen.begin(), bestLen.end()) - bestLen.begin();
    fout << bestLen[ansIndex] << '\n';

    std::vector<int> ansNumbers;
    ansNumbers.reserve(bestLen[ansIndex]);
    while (ansIndex != -1)
    {
        ansNumbers.push_back(numbers[sortedIndexes[ansIndex]]);
        ansIndex = previous[ansIndex];
    }

    std::reverse(ansNumbers.begin(), ansNumbers.end());

    for (int number: ansNumbers)
    {
        fout << number << ' ';
    }

    fout.close();

    return 0;
}