Cod sursa(job #2462264)

Utilizator preda.andreiPreda Andrei preda.andrei Data 26 septembrie 2019 22:28:50
Problema Subsir crescator maximal Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.4 kb
#include <algorithm>
#include <fstream>
#include <vector>

using namespace std;

class Bit
{
public:
    Bit(int size) : len_(size + 1, 0), pos_(size + 1, 0) {}

    void Add(int len, int num, int pos);

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

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

    vector<int> len_;
    vector<int> pos_;
};

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

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

    num += 1;
    while (num > 0) {
        if (len_[num] > best_len) {
            best_len = len_[num];
            best_pos = pos_[num];
        }
        num -= Lsb(num);
    }
    return {best_len, best_pos};
}

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

    vector<int> distinct;
    for (const auto &num : sorted) {
        if (distinct.empty() || num != distinct.back()) {
            distinct.push_back(num);
        }
    }
    return distinct;
}

int Index(const vector<int> &vec, int value)
{
    int pos = -1;
    int pow = (1 << 25);

    while (pow > 0) {
        int next_pos = pos + pow;
        pow >>= 1;

        if (next_pos < (int)vec.size() && vec[next_pos] <= value) {
            pos = next_pos;
        }
    }
    return pos;
}

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 distinct = Normalise(vec);
    Bit bit(distinct.size());

    vector<int> prev(n, -1);
    int best_len = 0;
    int best_pos = 0;

    for (int i = 0; i < n; i += 1) {
        auto index = Index(distinct, vec[i]);
        auto best = bit.Best(index - 1);

        prev[i] = best.second;
        bit.Add(best.first + 1, index, i);

        if (best.first > best_len) {
            best_len = best.first;
            best_pos = i;
        }
    }

    vector<int> lcs;
    while (best_pos >= 0) {
        lcs.push_back(vec[best_pos]);
        best_pos = prev[best_pos];
    }
    reverse(lcs.begin(), lcs.end());

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

    return 0;
}