Cod sursa(job #2746952)

Utilizator Ionut2791Voicila Ionut Marius Ionut2791 Data 28 aprilie 2021 18:27:22
Problema Subsir crescator maximal Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.24 kb
#include <bits/stdc++.h>
#define ll long long
#define sz(x) (int)(x).size()
#define LSB(a) ((-a) & a)
using namespace std;

#ifdef LOCAL
#define read() ifstream fin("date.in.txt");
#else
#define read() ifstream fin("scmax.in"); ofstream fout("scmax.out");
#endif // LOCAL

const int N = 100005;
int n, AIB[N];
int v[N];
int actPosInVector[N];
map<int,int> idx;
map<int,int> val;
int from[N];
vector<int> ans;

struct segmentTree {

    int sizee;
    vector<int> segs;
    vector<pair<int,int>> from;

    void init(int n) {
        sizee = 1;
        while(sizee < n)
            sizee *= 2;
        segs.assign(2 * sizee, 0);
        from.assign(2 * sizee, {-1, -1});
    }

    void setVal(int i, int x, int lx, int rx) {
        //cout << x << " " << lx << " " << rx << '\n';
        if(rx - lx == 1) {
            segs[x] = 1;
            from[x] = {i, i};
            //cout << x << " " << val[i] << '\n';
            return;
        }
        int m = (lx + rx) / 2;
        if(i < m)
            setVal(i, 2 * x + 1, lx, m);
        else
            setVal(i, 2 * x + 2, m, rx);

        if(i >= m && segs[x] < segs[2 * x + 1] + segs[2 * x + 2]) { // adica cat timp sunt pe ramura din stanga
            segs[x] = segs[2 * x + 1] + segs[2 * x + 2];
            from[x] = {2 * x + 1, 2 * x + 2};
        }
        else {
            if(segs[x] <= segs[2 * x + 1]) {
                from[x] = {2 * x + 1, -1};
                segs[x] = segs[2 * x + 1];
            }
            if(segs[x] < segs[2 * x + 2]) {
                from[x] = {2 * x + 2, -1};
                segs[x] = segs[2 * x + 2];
            }
        }
    }

    void setVal(int i) {
        setVal(i, 0, 0, sizee);
    }

    void computeAns(int x) {
        if(from[x].first == from[x].second) {
            ans.push_back(from[x].first);
            return;
        }

        if(from[x].first == 0)
            ans.push_back(x);
        else if(from[x].first != -1)
            computeAns(from[x].first);

        if(from[x].second == 0)
            ans.push_back(x);
        else if(from[x].second != -1)
            computeAns(from[x].second);
    }

    void afis() {
        int pw2 = 1, j = 0;
        while(j <= sizee) {
            int cnt = pw2;

            string s(((sizee * 2 - 1) / (cnt + 1)), ' ');

            if(pw2 * 2 > sizee)
                cout << " ";

            while(cnt--)
                cout << s << segs[j++];
            cout << '\n';
            pw2 *= 2;
        }
        cout << '\n';
    }
} tree;



int main() {
    read();
    fin >> n;

    for (int i = 1; i <= n; ++i) {
        fin >> v[i];
        idx[v[i]] = i;
    }
    int N = 0;
    for (pair<int,int> x : idx) {
        val[N] = x.first;
        idx[x.first] = N++;
    }

    --N;
    tree.init(N + 1);

    for (int i = 1; i <= n; ++i) {
        tree.setVal(idx[v[i]]);
        //tree.afis();
    }
    tree.computeAns(0);

    #ifdef LOCAL

    sort(ans.begin(), ans.end());
    cout << tree.segs[0] << '\n';
    for (int x : ans)
        cout << val[x] << " ";
    #else
    fout << tree.segs[0] << '\n';
    for (int x : ans)
        fout << val[x] << " ";
    #endif // LOCAL

    return 0;
}