Cod sursa(job #3344051)

Utilizator Dddarius95Darius-Florentin Neatu Dddarius95 Data 1 martie 2026 11:14:20
Problema Subsir crescator maximal Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.63 kb
// SPDX-License-Identifier: BSD-3-Clause

#include <algorithm>
#include <fstream> // ifstream, ofstream
#include <iostream> // cin, cout, cerr
#include <memory> // unique_ptr pentru Task
#include <vector> // vector
using namespace std;

class Task {
public:
    void solve() {
        read_input();
        write_output(get_result());
    }

private:
    int n;
    vector<int> v;
    vector<int> scmax_vec; // vectorul cu numerele din scmax

    void read_input() {
        ifstream fin("scmax.in");
        fin >> n;
        v.resize(n + 1);
        for (int i = 1; i <= n; ++i) {
            fin >> v[i];
        }
        fin.close();
    }

    int get_result() {
        // v   = vectorul dat
        // sol = lungimea SCMAX
        // pos = pozitia pe care se termina SCMAX gasit pentru problema data
        // solutia se termina cu                       v[pos]
        // inainte in solutie apare              v[prec[pos]]
        //                                v [prec[prec[pos]]]
        // si tot asa... in sir avem sol elemente!
        // Din cauza ca stim unde se termina solutia, o vom putea reconstrui in ordine inversa
        // (de la sfarsit catre inceput). Putem stoca rezultatul intr-un vector si sa il inversam la final.
        vector<int> dp(n + 1); // in explicatii indexarea incepe de la 1
        vector<int> prec(n + 1); // dp[1], ..., dp[n] | prec[1], ..., prec[n]

        // caz de baza
        dp[1] = 1; // [ v[1] ] este singurul subsir (crescator) care se termina pe 1
        prec[1] = 0; // nu are precedent

        // caz general
        for (int i = 2; i <= n; ++i) {
            dp[i] = 1; // [ v[i] ] - este un subsir (crescator) care se termina pe i
            prec[i] = 0; // nu are precedent (cel putin momentan)

            // incerc sa il pun pe v[i] la finalul tuturor solutiilor disponibile
            // o solutie se termina cu un element v[j]
            for (int j = 1; j < i; ++j) {
                // solutia triviala: v[i]
                if (v[j] < v[i]) {
                    // din (..., v[j]) pot obtine (..., v[j], v[i])
                    // (caz in care prec[i] = j)

                    // voi alege j-ul curent, cand alegerea imi gaseste o solutie mai buna decat ce am deja
                    if (dp[j] + 1 > dp[i]) {
                        dp[i] = dp[j] + 1;
                        prec[i] = j;
                    }
                }
            }
        }

        // solutia e maximul din vectorul dp
        int sol = dp[1], pos = 1;
        for (int i = 2; i <= n; ++i) {
            if (dp[i] > sol) {
                sol = dp[i];
                pos = i;
            }
        }

        // reconstruim SCMAX: v[pos] este ultimul element, inainte v[prec[pos]], etc.
        scmax_vec.clear();
        for (int i = 0; i < sol; ++i) {
            // v[pos] este ultimul element pe care il stiu din SCMAX
            scmax_vec.push_back(v[pos]);
            // inainte de el era v[prec[pos]] (..., v[ prec[pos] ], v[ pos ])
            pos = prec[pos];
        }
        reverse(scmax_vec.begin(), scmax_vec.end()); // oglindire vector solutie
        return sol;
    }

    void write_output(int result) {
        ofstream fout("scmax.out");
        // afiseaza solutia
        fout << result << "\n";
        for (size_t i = 0; i < scmax_vec.size(); ++i) {
            fout << (i ? " " : "") << scmax_vec[i];
        }
        fout << "\n";
        fout.close();
    }
};

// [ATENTIE] NU modifica functia main!
int main() {
    std::unique_ptr<Task> task {new (nothrow) Task()};
    if (!task) {
        std::cerr << "new failed: WTF are you doing? Throw your PC!\n";
        return -1;
    }
    task->solve();
    return 0;
}