Cod sursa(job #2800946)

Utilizator Andrei_TudorAndrei Tudor Andrei_Tudor Data 14 noiembrie 2021 15:53:39
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.01 kb
#include <fstream>
#include <vector>
#include <limits>
#include <algorithm>
#include <cassert>

using namespace std;

int binarySearch(const vector <int>& dp, const int& value) {
    // https://en.cppreference.com/w/cpp/algorithm/lower_bound
    return distance(dp.begin(), lower_bound(dp.begin(), dp.end(), value)) - 1;
}

int main(){
    ifstream cin ("scmax.in");
    ofstream cout ("scmax.out");
    int n;
    cin >> n;
    vector <int> values(n);
    for(int i = 0; i < n; ++ i){
        cin >> values[i];
    }
    vector <int> dp(n + 1, numeric_limits<int>::max());
    dp[0] = 0;
    // dp[i] = cea mai mica valoare in care se poate termina
    //         o secventa de lungime i
    // dp[j][i] = cea mai mica valoare in care se poate termina
    //            o secventa de lungime i, dupa ce am procesat primele 
    //            j elemente
    // mereu dp[j][i] depinde de dp[j-1][valoare] cu valoare iterata
    // dp[1][i=1] = 24; // infoarena exemplu dp[1] = 24
    // dp[2][i=1] = 12                       dp[1] = 12 // suprascrie 24
    // dp[3][i=2] = 15                       dp[2] = 15
    // dp[4][i=2] = 15                       dp[2] = 15
    vector <int> lengthToOriginalPosition(n + 1);
    lengthToOriginalPosition[0] = -1;
    // Cand suntem la o lungime L, practic noi stim care este ultima valoare V
    // in care un subsir crescator maximal de lungime L se termina.
    // Pentru V noi stim si pozitia pe care aceasta se afla in vectorul initial.
    // Acum avem nevoie de un vector care sa ne tina pentru o lungime L pozitia
    // din vectorul values al valorii corespunzatoare respectivului subsir
    // crescator maximal.
    vector <int> originalPositionToPreviousPosition(n + 1, -1);
    // Sa presupunem ca avem un subsir crescator maximal de lungime L care se 
    // termina intr-o valoare V. Pentru acea valoare V cunoastem care este pozitia
    // sa in vectorul original (i.e. lengthToOriginalPosition[L]) si acum dorim 
    // sa cream o relatie intre pozitia valorii V si pozitia valorii Q, unde Q este
    // valoare de dinainte de V in subsirul crescator maximal despre care discutam.
    pair<int, int> best = {0, 0};
    // .first este length
    // .second este pozitia ultimului pentru lungimea .first
    for (int i = 0; i < n; i ++) { /// schimba modul cum iteram
        // place your code
        // elem will be placed on pos + 1
        int k = binarySearch(dp, values[i]);
        dp[k + 1] = values[i];
        originalPositionToPreviousPosition[i] = lengthToOriginalPosition[k];
        lengthToOriginalPosition[k + 1] = i;
        best = max(best, {k + 1, i});        
    }
    cout << best.first << "\n";
    // output the sequence!
    auto outputSequence = [&](auto&& self, int position) -> void {
        if (position == -1) {
            return;
        }
        self(self, originalPositionToPreviousPosition[position]);
        cout << values[position] << ' ';
    };
    outputSequence(outputSequence, best.second);
    return 0;
}