Cod sursa(job #847192)

Utilizator vendettaSalajan Razvan vendetta Data 3 ianuarie 2013 15:32:30
Problema Subsir crescator maximal Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.25 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

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

#define nmax 100005
#define ll long long

int n, dp[nmax], t[nmax], aint[nmax*4];
pair<int,int> v[nmax];
int poz[nmax], v2[nmax];
int p2[nmax];

void citeste(){
    f >> n;
    int x=0;
    for(int i=1; i<=n; ++i){
        f >> x;
        v[i] = make_pair(x, i);
        v2[i] = x;
    }
    sort(v+1, v+n+1);
}

void udpate(int nod, int st, int dr, int poz, int val){
    if (st == dr){
        aint[nod] = val;
        return;
    }else {
        int mij = (st + dr) / 2;
        if (poz <= mij) udpate(nod*2, st, mij, poz, val);
                   else udpate(nod*2+1, mij+1, dr, poz, val);

        aint[nod] = aint[nod*2];
        if ( dp[ aint[nod*2+1] ] > dp[ aint[nod] ] ){
            aint[nod] = aint[nod*2+1];
        }
    }
}

void query(int nod, int st, int dr, int a, int b, int &cine){
    if (a <= st && dr <= b){
        if (dp[ cine ] < dp[ aint[nod] ]){
            cine = aint[nod];
        }
        return;
    }else {
        int mij = (st + dr) / 2;
        if (a <= mij) query(nod*2, st, mij, a, b, cine);
        if (b > mij) query(nod*2+1, mij+1, dr, a, b, cine);
    }
}

void fa_drum(int x){
    if (t[x] != 0) fa_drum(t[x]);
    g << v2[x] << " ";
}

void rezolva(){
    for(int i=1; i<=n; ++i){
        poz[ v[i].second ] = i; //pozitia in vectorul sortat a fiecarui element initial
        if (v[i].first == v[i-1].first){//in caz ca sunt identice
            p2[ v[i].second ] = p2[ v[i-1].second ];
        }else p2[ v[i].second ] = i;
    }

    int poz2 = 0; int Max = 0;
    for(int i=1; i<=n; ++i){
        int cine = 0;
        if (p2[i]-1>0) query(1, 1, n, 1, p2[i]-1, cine);//vad acum cel mai mare dp[ i ] pentru toate numerele mai mici ca si v[i]
        dp[ i ] = dp[ cine ] + 1;
        t[ i ] = cine;
        udpate(1, 1, n, poz[i], i);
        if (Max < dp[i]){
            Max = dp[i];
            poz2 = i;
        }
    }
    //cout << Max << "\n";
    g << Max << "\n";
    fa_drum(poz2);
}

int main(){
    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;
}