Cod sursa(job #2462233)

Utilizator preda.andreiPreda Andrei preda.andrei Data 26 septembrie 2019 21:53:13
Problema Subsir crescator maximal Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
#include <algorithm>
#include <fstream>
#include <map>
#include <vector>

using namespace std;

class Normaliser
{
public:
    Normaliser(const vector<int> &vec);

    int Size() const { return values_.size(); }

    int Index(int value) const { return indexes_.at(value); }

    int Value(int index) const { return values_[index - 1]; }

private:
    map<int, int> indexes_;
    vector<int> values_;
};

Normaliser::Normaliser(const vector<int> &vec)
{
    vector<int> sorted(vec.begin(), vec.end());
    sort(sorted.begin(), sorted.end());

    for (const auto &num : sorted) {
        if (values_.empty() || num != values_.back()) {
            indexes_[num] = indexes_.size() + 1;
            values_.push_back(num);
        }
    }
}

class Bit
{
public:
    Bit(int size) : len_(size + 2, 0), num_(size + 2, 0) {}

    void Add(int len, int num);

    pair<int, int> Best(int num) const;

    pair<int, int> BestAll() const { return Best(len_.size() - 1); }

private:
    static int Lsb(int num) { return num & -num; }

    vector<int> len_;
    vector<int> num_;
};

void Bit::Add(int len, int num)
{
    int pos = num;
    while (pos < (int)len_.size()) {
        if (len > len_[pos]) {
            len_[pos] = len;
            num_[pos] = num;
        }
        pos += Lsb(pos);
    }
}

pair<int, int> Bit::Best(int num) const
{
    int best_len = 0;
    int best_num = 0;

    while (num > 0) {
        if (len_[num] > best_len) {
            best_len = len_[num];
            best_num = num_[num];
        }
        num -= Lsb(num);
    }
    return {best_len, best_num};
}

map<int, int> Normalise(const vector<int> &vec)
{
    vector<int> sorted(vec.begin(), vec.end());
    sort(sorted.begin(), sorted.end());

    map<int, int> index;
    int last = -1;

    for (const auto &num : sorted) {
        if (num != last) {
            index[num] = index.size() + 1;
        }
        last = num;
    }
    return index;
}

vector<int> Reconstruct(const Normaliser &normaliser, const Bit &bit)
{
    int index = bit.BestAll().second;
    vector<int> seq;

    while (index > 0) {
        seq.push_back(normaliser.Value(index));
        index = bit.Best(index - 1).second;
    }

    reverse(seq.begin(), seq.end());
    return seq;
}

vector<int> LongestIncreasing(const vector<int> &vec)
{
    Normaliser normaliser(vec);
    Bit bit(normaliser.Size());

    for (const auto &num : vec) {
        auto index = normaliser.Index(num);
        auto prev = bit.Best(index - 1);
        bit.Add(prev.first + 1, index);
    }
    return Reconstruct(normaliser, bit);
}

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

    int n;
    fin >> n;

    vector<int> vec(n);
    for (auto &num : vec) {
        fin >> num;
    }

    auto res = LongestIncreasing(vec);
    fout << res.size() << "\n";

    for (const auto &num : res) {
        fout << num << " ";
    }
    fout << "\n";

    return 0;
}