Cod sursa(job #1780095)

Utilizator preda.andreiPreda Andrei preda.andrei Data 15 octombrie 2016 20:46:29
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.37 kb
#include <algorithm>
#include <fstream>
#include <vector>

using namespace std;

inline int PutereZerouri(int x)
{
    return (x ^ (x - 1)) & x;
}

vector<int> Normalizeaza(const vector<int> &v)
{
    vector<int> sortat(v);
    sort(sortat.begin(), sortat.end());

    vector<int> normal;
    normal.push_back(-1);
    for (unsigned i = 0; i < v.size(); ++i) {
        if (i == 0 || sortat[i] != sortat[i - 1])
            normal.push_back(sortat[i]);
    }
    return normal;
}

int AflaPozitie(const vector<int> &normal, int x)
{
    int st = 1, dr = normal.size() - 1;
    while (st <= dr) {
        int mij = st + (dr - st) / 2;
        if (normal[mij] == x)
            return mij;
        if (normal[mij] > x)
            dr = mij - 1;
        else st = mij + 1;
    }
    return 0;
}

int AflaIndiceMaxim(const vector<int> &aib, const vector<int> &lmax, int poz)
{
    int raspuns = 0;
    while (poz > 0) {
        if (lmax[aib[poz]] > lmax[raspuns])
            raspuns = aib[poz];
        poz -= PutereZerouri(poz);
    }
    return raspuns;
}

void Actualizeaza(vector<int> &aib, const vector<int> &lmax, int poz, int ind)
{
    while (poz < aib.size()) {
        if (lmax[ind] > lmax[aib[poz]])
            aib[poz] = ind;
        poz += PutereZerouri(poz);
    }
}

void AfiseazaSir(const vector<int> &val, const vector<int> &pred, int poz, ofstream &f)
{
    if (pred[poz] > 0)
        AfiseazaSir(val, pred, pred[poz], f);
    f << val[poz] << " ";
}

int main()
{
    ifstream fin("scmax.in");
    ofstream fout("scmax.out");

    int n;
    fin >> n;

    vector<int> valori(n + 1);
    for (int i = 1; i <= n; ++i)
        fin >> valori[i];

    auto normal = Normalizeaza(valori);
    vector<int> aib(normal.size(), 0);
    vector<int> lmax(n + 1, 0);
    vector<int> predecesor(n + 1, 0);

    int raspuns = 0, poz_raspuns = 0;
    for (int i = 1; i <= n; ++i) {
        int poz = AflaPozitie(normal, valori[i]);
        int pred = AflaIndiceMaxim(aib, lmax, poz - 1);

        lmax[i] = (pred == 0) ? 1 : lmax[pred] + 1;
        predecesor[i] = pred;
        Actualizeaza(aib, lmax, poz, i);

        if (lmax[i] > raspuns) {
            raspuns = lmax[i];
            poz_raspuns = i;
        }
    }

    fout << raspuns << "\n";
    AfiseazaSir(valori, predecesor, poz_raspuns, fout);
    return 0;
}