Cod sursa(job #2120397)

Utilizator preda.andreiPreda Andrei preda.andrei Data 2 februarie 2018 13:37:23
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.56 kb
#include <algorithm>
#include <fstream>
#include <vector>

using namespace std;

struct BitNode
{
    int len, pos;

    BitNode(int len, int pos) : len(len), pos(pos) {}
    BitNode() : BitNode(0, 0) {}

    bool operator<(const BitNode &other) const
    {
        return len < other.len;
    }
};

class Bit
{
public:
    Bit(int size) : nodes_(vector<BitNode>(size + 1)) {}

    void Update(int ind, int len, int pos);

    BitNode Query(int ind);

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

private:
    vector<BitNode> nodes_;
};

void Bit::Update(int ind, int len, int pos)
{
    BitNode new_node(len, pos);
    while (ind < (int)nodes_.size()) {
        nodes_[ind] = max(nodes_[ind], new_node);
        ind += Lsb(ind);
    }
}

BitNode Bit::Query(int ind)
{
    BitNode res(0, -1);
    while (ind > 0) {
        res = max(res, nodes_[ind]);
        ind -= Lsb(ind);
    }
    return res;
}

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

    vector<int> normal{sorted[0]};
    for (const auto &elem : sorted) {
        if (elem != normal.back()) {
            normal.push_back(elem);
        }
    }
    return normal;
}

int FindOrder(const vector<int> &normal, int elem)
{
    int res = -1;
    int power = (1 << 25);

    while (power > 0) {
        auto next_res = res + power;
        if (next_res < (int)normal.size() && normal[next_res] <= elem) {
            res = next_res;
        }
        power >>= 1;
    }
    return res;
}

vector<int> FindLis(const vector<int> &vec)
{
    auto normal = Normalise(vec);
    Bit bit(normal.size());

    vector<int> prev(vec.size());
    for (size_t i = 0; i < vec.size(); ++i) {
        auto order = FindOrder(normal, vec[i]) + 1;
        auto best_prev = bit.Query(order - 1);

        prev[i] = best_prev.pos;
        bit.Update(order, best_prev.len + 1, i);
    }

    auto best_end = bit.Query(normal.size());
    vector<int> lis(best_end.len);

    auto ind = best_end.pos;
    for (int i = lis.size() - 1; i >= 0; --i) {
        lis[i] = vec[ind];
        ind = prev[ind];
    }
    return lis;
}

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

    int n;
    fin >> n;

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

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

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

    return 0;
}