Cod sursa(job #1786614)

Utilizator DevilOnFieldTudor Horia Niculescu DevilOnField Data 23 octombrie 2016 13:22:27
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.75 kb
#include<stdio.h>
#include<algorithm>

#define P 17
#define PRINT 0

using namespace std;

FILE *in, *out;

struct elem
{
    int val, poz, i;
};

elem v[100001];
int c[100001], d[100001], n, poz;

bool normal(elem a, elem b)
{
    if (a.val == b.val) return a.val<b.val;
    return a.val < b.val;
}

bool back(elem a, elem b)
{
    return a.i < b.i;
}

int findbin(int val, int lmax) {
    int a, b, m;
    a = 0;
    b = lmax;
    int p = (1 << P);
    while(p > 0) {
        if((p + a) <= lmax && c[a + p] < val) {
            a = a + p;
        }
        p = (p >> 1);
    }

    return a;
/*
    while (a < b) {
        //printf("sS");
        m = (a + b) / 2;
        if(c[m] == val) {
            b = m - 1;
            break;
        } else {
            if(c[m] < val) {
                a = m;
            } else {
                b = m - 1;
            }
        }
    }

    return b;
*/
}

int main ()
{
    in = fopen("scmax.in", "r");
    out = fopen("scmax.out", "w");

    fscanf(in, "%d", &n);

    v[0].val = 0;
    poz = 1;
    int numero;
    for(int i = 1; i <= n; i++) {
        fscanf(in, "%d", &numero);
        if(numero != v[poz - 1].val) {
            v[poz].val = numero;
            v[poz].i = poz;
            poz++;
        }
    }
    n = poz - 1;

    sort(v + 1, v + n + 1, normal);
    poz = 1;
    v[1].poz = poz;
    for(int i = 2; i <= n; i++) {
        if (v[i].val!=v[i-1].val) poz++;
        v[i].poz=poz;
    }
    sort(v+1,v+n+1,back);
    if(PRINT) {
        for(int i = 1; i <= n; i++) {
            fprintf(stdout, "%d ", v[i].poz);
        } printf("\n");
    }
    int bun;
    int maxim = 0;
    for(int i = 1; i <= n; i++) {
        bun = findbin(v[i].poz, d[maxim]);
        if (PRINT) {
            printf ("%d %d %d CB\n",bun,v[i].poz,d[maxim]);
        }
        d[i] = bun + 1;
        if(d[i] > d[maxim]) {
            maxim = i;
        }
        if(v[i].poz < c[d[i]] || (c[d[i]] == 0 && d[i] != 0)) {
            c[d[i]] = v[i].poz;
        }
        if(PRINT)
        {
            for(int i = 1; i <= n; i++) {
                fprintf(stdout, "%d ", d[i]);
            } printf("DDD\n");
            for(int i = 0; i <= d[maxim]; i++) {
                fprintf(stdout, "%d ", c[i]);
            } printf("CCC\n\n\n");
        }
    }
    fprintf(out, "%d\n", d[maxim]);
//(v + 1, v + n + 1, back);
    numero = maxim;
    int last = v[maxim].val;
    int toto = d[maxim] - 1;
    c[d[maxim]]=v[maxim].val;
    while(toto > 0 &&numero>=0) {
        if(v[numero].val < last &&d[numero]==toto) {
            c[toto] = v[numero].val;
            last = v[numero].val;
            toto--;
        }
        numero--;
    }
    for(int i = 1; i <= d[maxim]; i++) {
        fprintf(out, "%d ", c[i]);
    }
    fclose(in);
    fclose(out);

    return 0;
}