Cod sursa(job #1997880)

Utilizator savigunFeleaga Dragos-George savigun Data 5 iulie 2017 18:05:16
Problema Subsir crescator maximal Scor 90
Compilator cpp Status done
Runda Arhiva educationala Marime 3.31 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;

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

int n, bl, pre[100005], bp, before[100005];
pair<int, int> v[100005];
vector<int> sol;

struct Node {
    int val, prev, pos;
};

class SegmentTree {
public:
    int n;
    Node* tree;

    SegmentTree(int n) {
        this->n = n;
        tree = new Node[4 * n]();
    }

    void update2(int id, int start, int end, int pos, int val, int prev, int idx) {
        if (start > pos || end < pos) return;

        if (start == end) {
            tree[id].val = val;
            tree[id].prev = prev;
            tree[id].pos = idx;
            return;
        }

        int mid = (start + end) / 2;
        update2(id * 2, start, mid, pos, val, prev, idx);
        update2(id * 2 + 1, mid + 1, end, pos, val, prev, idx);

        if (tree[id * 2].val >= tree[id * 2 + 1].val) {
            tree[id] = tree[id * 2];
        } else {
            tree[id] = tree[id * 2 + 1];
        }
    }

    void update(int id, int start, int end, int pos, int val, int prev) {
        if (start > pos || end < pos) return;

        if (start == end) {
            tree[id].val = val;
            tree[id].prev = prev;
            return;
        }

        int mid = (start + end) / 2;
        update(id * 2, start, mid, pos, val, prev);
        update(id * 2 + 1, mid + 1, end, pos, val, prev);

        if (tree[id * 2].val >= tree[id * 2 + 1].val) {
            tree[id] = tree[id * 2];
        } else {
            tree[id] = tree[id * 2 + 1];
        }
    }

    Node query(int id, int start, int end, int a, int b) {
        if (start > b || end < a) return {0, 0, 0};

        if (start >= a && end <= b) return tree[id];

        int mid = (start + end) / 2;

        Node left = query(id * 2, start, mid, a, b);
        Node right = query(id * 2 + 1, mid + 1, end, a, b);
        if (left.val >= right.val) return left;
        return right;
    }
} *T;


int main()
{
    in >> n;
    for (int i = 1; i <= n; ++i) {
        in >> v[i].first;
        v[i].second = i;
        before[i] = v[i].first;
    }

    sort(v + 1, v + n + 1);

    int last = 1;
    for (int i = 1; i <= n; ++i) {
        bool ok = false;
        if (v[i + 1].first > v[i].first) ok = true;
        v[i].first = last;
        if (ok) last++;
    }

    sort(v + 1, v + n + 1, [](pair<int, int> a, pair<int, int> b) -> bool {
        return a.second < b.second;
    });


    T = new SegmentTree(n);
    for (int i = 2; i <= n; ++i) {
        T->update2(1, 1, n, v[i].first, 0, i, i);
    }

    T->update2(1, 1, n, v[1].first, 1, 1, 1);

    for (int i = 2; i <= n; ++i) {
        Node best = T->query(1, 1, n, 1, v[i].first - 1);
        if (best.val == 0) {
            best.pos = 0;
            best.prev = 0;
        }
        T->update(1, 1, n, v[i].first, best.val + 1, best.pos);
        pre[i] = best.pos;
        if (best.val + 1 > bl) {
            bl = best.val + 1;
            bp = i;
        }
    }

    out << bl << "\n";
    while (bp != 0) {
        sol.push_back(before[bp]);
        bp = pre[bp];
    }

    for (int i = sol.size() - 1; i >= 0; --i) {
        out << sol[i] << " ";
    }

    return 0;
}