Cod sursa(job #3339452)

Utilizator vndianamaria@gmail.comIvan Diana [email protected] Data 8 februarie 2026 10:21:29
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.46 kb
#include <fstream>
        #define DIM 100010
        using namespace std;
        /* LIS
        mentinem pentru fiecare lungime L cea mai mica valore posibila cu care se poate
        termina un subsir crescator de lungime L, folosind elementele parcurse pana acum
        pentru a putea reconstrui o solutie, retinem parintele fiecarui element folosit
        
        aici nu se tin minte direct valorile, ci indicii in v
        d[len] = indicele din v al elementului care reprezinta "cel mai bun capat"
                 (valoarea minima) pentru un subsir crescator de lungime len
                 */
        int V[DIM], T[DIM], D[DIM];
        int n, m, i, p, u, mid;
        /**
        D[i] = indicele din V al celei mai mici valori in care se poate
        termina un sir de lungime i (de fapt D[i] = poZitia din V a unei
        astfel de valori) folosind elementele deja parcurse
        
        m = lungimea maxima LIS gasita pana acum
        p, u = capete in cautarea binara (p - st, u - dr)
        **/
        ifstream cin("scmax.in");
        ofstream cout("scmax.out");
        void sol(int i) {
            if (i) {
                sol(T[i]);
                cout<<V[i]<<" ";
            }
        }
        int main() {
            cin>>n;
            
            for (i=1;i<=n;i++)
                cin>>V[i];
                
            m = 1;
            D[1] = 1;
            // parcurgem elementul curent v[i], vrem sa ii gasim lungimea la care poate fi plasat
            // cautam prima pozitie p in 1..m pentru care v[d[p]] >= v[i]
            // asta inseamna pentru toate lungimile < p, capatul este < v[i], deci putem extinde
            // la p, capatul este >= v[i], deci v[i] poate "ibunatati" capatul (devine mai mic)
            // exact aceasta este bs clasic pe vectorul de capete
            for (i=2;i<=n;i++) {
                p = 1; ///caut pozitia ultimei valori D[poz] din
                /// D pentru care V[i] > V[ D[poz] ]
                u = m;
                while (p<=u) {
                    mid = p+(u-p)/2;
                    // d[mid] este un indice din v, deci capatul pentru lungimea mid este v[d[mid]]
                    if (V[ D[mid] ] >= V[i])
                        // cautam mai in stanga, vrem prima pozitie cu >=
                        u = mid - 1;
                    else
                        // capatul este < v[i], deci putem extinde cel putin pana aici
                        p = mid + 1;
                }
                /**
                dupa:
                    p: prima pozitie unde v[d[p]] >= v[i] (sau p = m + 1 daca nu exista)
                    u: ultima pozitie unde v[d[u]] < v[i]
                    obs: u = p - 1
                        lungimea maxima pe care o putem extinde cu v[i] este u
                **/
                if (p > m) {
                    // inseamna ca v[i] este mai mare decat toate capetele curente, deci
                    // putem extinde LIS ul maxim: crestem m, noul capat pentru lungime m devine i
                    m++;
                    D[m] = i;
                    
                    // parintele lui i este capatul optim al subsirului de lungime m-1
                    T[i] = D[p-1];
                } else {
                    D[p] = i;
                    T[i] = D[p-1];/// extind sirul terminat pe pozitia p-1(u)
                }
            }
            cout<<m<<"\n";
            
            sol(D[m]); ///in T este un vector de tati pentru indici din V
            
            return 0;
        }