Cod sursa(job #3309102)

Utilizator CatalinPangaleanuCatalin Pangaleanu CatalinPangaleanu Data 1 septembrie 2025 02:49:10
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.31 kb
#include <fstream>
#include <vector>
#include <algorithm>

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

    if (treeLeft == left && treeRight == right)
        return segmentTree[node];

    int treeMiddle = (treeLeft + treeRight) / 2;

    std::pair<int, int> resultLeft = querySegmentTree(segmentTree, 2 * node + 1, treeLeft, treeMiddle, left, std::min(right, treeMiddle));
    std::pair<int, int> resultRight = querySegmentTree(segmentTree, 2 * node + 2, treeMiddle + 1, treeRight, std::max(treeMiddle + 1, left), right);

    if (resultLeft.first > resultRight.first)
        return resultLeft;

    return resultRight;
}

void updateSegmentTree(std::vector<std::pair<int, int>> &segmentTree, int node, int left, int right, int position, std::pair<int, int> value)
{
    if (left == right)
    {
        segmentTree[node] = value;

        return;
    }

    int middle = (left + right) / 2;

    if (position <= middle)
        updateSegmentTree(segmentTree, 2 * node + 1, left, middle, position, value);
    else
        updateSegmentTree(segmentTree, 2 * node + 2, middle + 1, right, position, value);

    if (segmentTree[2 * node + 1].first > segmentTree[2 * node + 2].first)
        segmentTree[node] = segmentTree[2 * node + 1];
    else
        segmentTree[node] = segmentTree[2 * node + 2];
}

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

    int n;
    inFile >> n;

    std::vector<int> numbers(n), sortedNumbers(n);

    for (int i = 0; i < n; ++i)
    {
        inFile >> numbers[i];

        sortedNumbers[i] = numbers[i];
    }

    inFile.close();

    std::sort(sortedNumbers.begin(), sortedNumbers.end());
    auto endIt = std::unique(sortedNumbers.begin(), sortedNumbers.end());
    sortedNumbers.erase(endIt, sortedNumbers.end());

    std::vector<int> sortedIndex(n);

    for (int i = 0; i < n; ++i)
    {
        sortedIndex[i] = (int) (std::lower_bound(sortedNumbers.begin(), sortedNumbers.end(), numbers[i]) - sortedNumbers.begin());
    }

    std::vector<std::pair<int, int>> segmentTree(4 * sortedNumbers.size(), {0, -1});
    std::vector<int> bestLength(sortedNumbers.size()), previous(sortedNumbers.size());

    for (int i = 0; i < n; ++i)
    {
        std::pair<int, int> result = querySegmentTree(segmentTree, 0, 0, (int) sortedNumbers.size() - 1, 0, sortedIndex[i] - 1);

        if (result.first + 1 > bestLength[sortedIndex[i]])
        {
            bestLength[sortedIndex[i]] = result.first + 1;
            previous[sortedIndex[i]] = result.second;

            updateSegmentTree(segmentTree, 0, 0, (int) sortedNumbers.size() - 1, sortedIndex[i], {result.first + 1, sortedIndex[i]});
        }
    }

    int endIndex = (int) (std::max_element(bestLength.begin(), bestLength.end()) - bestLength.begin());

    std::vector<int> indexPath;
    indexPath.push_back(endIndex);

    while (previous[indexPath.back()] != -1)
    {
        indexPath.push_back(previous[indexPath.back()]);
    }

    std::ofstream outFile;
    outFile.open("scmax.out");

    outFile << bestLength[indexPath.front()] << '\n';

    for (int i = (int) indexPath.size() - 1; i >= 0; --i)
    {
        outFile << sortedNumbers[indexPath[i]] << ' ';
    }

    outFile.close();

    return 0;
}