Cod sursa(job #3155576)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 8 octombrie 2023 18:12:25
Problema Subsir crescator maximal Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.42 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream f("scmax.in");
ofstream g("scmax.out");

class FenwickTree
{
    static constexpr int NMAX = (int)(1e5 + 1);

    int n;
    int a[NMAX];

private:
    static inline int lsb(const int &x)
    {
        return (x & (-x));
    }

    static inline int my_max(const int &a, const int &b)
    {
        return ((a > b) ? a : b);
    }

public:
    inline void init(const int &m)
    {
        n = m;
        return;
    }

    inline void update(const int &pos, const int &val)
    {
        for (int i = pos; i <= n; i += lsb(i))
            a[i] = my_max(a[i], val);
        return;
    }

    inline int query(const int &pos)
    {
        int ans = 0;

        for (int i = pos; i >= 1; i -= lsb(i))
            ans = my_max(ans, a[i]);
        return ans;
    }
} T;

static inline vector<int> elim_duplicates(vector<int> &V)
{
    vector<int> v = V;

    sort(v.begin(), v.end());

    vector<int> q = {v[0]};

    for (int i = 1; i < (int)v.size(); ++i)
        if (v[i] != v[i - 1])
            q.push_back(v[i]);

    return q;
}

static inline vector<int> lis(vector<int> a)
{
    vector<int> q = elim_duplicates(a);

    int Max = 0;
    for (auto &it : a)
        if (it > Max)
            Max = it;

    T.init(Max);

    vector<int> dp = {};
    for (int i = 0; i < (int)a.size(); ++i)
        dp.push_back(0);

    int best = 0, pos = -1;

    for (int i = 0; i < (int)a.size(); ++i)
    {
        int x = (int)(lower_bound(q.begin(), q.end(), a[i]) - q.begin()) + 1;

        dp[i] = 1 + T.query(x - 1);

        T.update(x, dp[i]);

        if (dp[i] > best)
            best = dp[i], pos = i;
    }

    vector<int> ans = {};

    if (pos >= 0)
    {
        ans.push_back(a[pos]);
        --best;

        for (int i = (pos - 1); i >= 0 && best >= 0; --i)
            if (dp[i] == best && a[i] < a[pos])
                ans.push_back(a[i]), --best, pos = i;

        reverse(ans.begin(), ans.end());
    }

    return ans;
}

int main()
{
    int n = 0;

    f.tie(nullptr);
    f >> n;

    vector<int> a = {};

    for (int i = 0; i < n; ++i)
    {
        int x = 0;
        f >> x;

        a.push_back(x);
    }

    vector<int> ans = lis(a);

    g << ans.size() << '\n';
    for (int i = 0; i < (int)ans.size(); ++i)
    {
        g << ans[i];

        if (i != (int)ans.size() - 1)
            g << ' ';
        else
            g << '\n';
    }

    return 0;
}