Cod sursa(job #2961108)

Utilizator Alex18maiAlex Enache Alex18mai Data 5 ianuarie 2023 20:06:26
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.06 kb
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>

using namespace std;

// ifstream cin("input");ofstream cout("output");
ifstream cin("scmax.in");ofstream cout("scmax.out");

// SOLUTIE O(N logN)

const int inf = 2e9 + 1;

int n;

vector<int> numere;

vector<int> dp;
// dp[i] = pozitia din vector (numere) a celei mai mici valori de pana acum
//         care se afla la finalul unui subsir strict crescator de lungime i

vector<int> inainte; // inainte[i] = care este pozitia numarului care vine inaintea mea (folosesc la afisare)

int MAX; // raspunsul = lungimea maxima

void citire() {
    cin >> n;

    numere.resize(n+2);
    dp.resize(n+2);
    inainte.resize(n+2);

    for (int i = 1; i <= n; i++) {
        cin >> numere[i];
        dp[i] = n + 1; // initializez cu pozitia n+1 care reprezinta infinitul
    }
    numere[n + 1] = inf; // ii dau valoarea de infinit
}

int cautBin(int i) {
    int st = 0, dr = i - 1;
    int ans = 0;
    while (st <= dr) {
        int mij = st + dr;
        mij /= 2;
        if (numere[i] > numere[dp[mij]]) {
            ans = mij;
            st = mij + 1;
        }
        else {
            dr = mij - 1;
        }
    }
    return ans;
}

void rezolvare() {
    for (int i = 1; i <= n; i++) {
        int ans = cautBin(i); // caut lungimea maxima la care pot sa ma lipesc

        if (numere[i] < numere[dp[ans + 1]]) { // actualizez dinamica doar daca eu sunt mai mic
            dp[ans + 1] = i; // eu devin capatul subsirului de lungima ans + 1
        }
        inainte[i] = dp[ans]; // actualizez pozitia inaintea mea (vin din dp[ans])

        MAX = max(MAX, ans + 1); // actualizez lungimea celui mai lung subsir crescator
    }
}

void afisare() {
    cout << MAX << '\n';

    vector < int > raspuns;
    int now = dp[MAX];
    while (now) {
        raspuns.push_back(numere[now]);
        now = inainte[now];
    }
    reverse(raspuns.begin(), raspuns.end());
    for (auto& x : raspuns) {
        cout << x << " ";
    }
    cout << '\n';
}

int main(){

    citire();
    rezolvare();
    afisare();

}