Cod sursa(job #1267477)

Utilizator cernat.catallinFMI Cernat Catalin Stefan cernat.catallin Data 19 noiembrie 2014 22:36:00
Problema Subsir crescator maximal Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.35 kb
#include <stdio.h>
#include <assert.h>
#include <algorithm>
#include <iostream>
using namespace std;



class Reader {
    public:
        Reader(FILE *stream, const size_t size = (1 << 16)):
            size(size),
            pointer(0),
            stream(stream) {
                buffer = (char*) malloc(size);
                assert(fread(buffer, 1, size, this->stream) != 0);
            }

        ~Reader() {
            free(buffer);
        }

        template<typename IntType>
            IntType NextInt() {
                IntType value = 0;
                bool negative = false;
                while ((Current() < '0' || Current() > '9') && Current() != '-')
                    NextPosition();
                if (Current() == '-'){
                    negative = true;
                    NextPosition();
                }
                while (Current() >= '0' && Current() <= '9'){
                    value = value * 10 + Current() - '0';
                    NextPosition();
                }
                if (negative)
                    value = -value;
                return value;
            }

        Reader& operator>>(short &value) {
            value = NextInt<short>();
            return *this;
        }

        Reader& operator>>(int &value) {
            value = NextInt<int>();
            return *this;
        }

        Reader& operator>>(long long &value) {
            value = NextInt<long long>();
            return *this;
        }
       
    private:
        size_t size;
        size_t pointer;
        char *buffer;
        FILE *stream;

        char Current() const {
            return buffer[pointer];
        }

        void NextPosition() {
            if (++pointer == size) {
                assert(fread(buffer, 1, size, stream) != 0);
                pointer = 0;
            }
        }
};

const int Nmax = 100005;

int n;
// initial vector | sorted vector with unique elements | normalized vector (norm[i] = pozition of v[i] in the sorted vector
int v[Nmax], vu[Nmax], norm[Nmax];
// aib tree | length of max sequence | trace path vector
int aib[Nmax], l[Nmax], t[Nmax];



void update(int idx, int i) {
    for (; idx <= n; idx += (idx & -idx))
        if (l[i] > l[aib[idx]])
            aib[idx] = i;
}

int query(int idx) {
    int maxx = 0;
    for (; idx; idx -= (idx & -idx))
        if (l[maxx] < l[aib[idx]])
            maxx = aib[idx];
    return maxx;
}

int bsearch(int* a, int n, int x) {
    int pos = 0;
    int pas = 1 << 17;
    while (pas >>= 1)
        if (pos + pas <= n && a[pos + pas] <= x)
            pos += pas;
    return pos;
}

int main() {
    freopen("scmax.in", "r", stdin);
    freopen("scmax.out", "w", stdout);
    int m = 1, best = 0;

    scanf("%d", &n);
    Reader in(stdin);
    for (int i = 1; i <= n; ++i) {
        in >> v[i];
        norm[i] = vu[i] = v[i];
    }
    
    sort(vu + 1, vu + n + 1);
    for (int i = 2; i <= n; ++i)
        if (vu[m] != vu[i])
            vu[++m] = vu[i];
    for (int i = 1; i <= n; ++i)
        norm[i] = bsearch(vu, m, v[i]);

    for (int i = 1; i <= n; ++i) {
        t[i] = query(norm[i] - 1);
        l[i] = l[t[i]] + 1;
        update(norm[i], i);
        if (l[i] > l[best])
            best = i;
    }

    printf("%d\n", l[best]);
    for (m = 0; best; best = t[best])
        vu[++m] = v[best];
    for (int i = m; i; --i)
        printf("%d ", vu[i]);

    return 0;
}