Cod sursa(job #1536057)

Utilizator DysKodeTurturica Razvan DysKode Data 25 noiembrie 2015 16:48:29
Problema Subsir crescator maximal Scor 35
Compilator cpp Status done
Runda Arhiva educationala Marime 2.73 kb
#include <fstream>
#include <algorithm>

using namespace std;

#define f first
#define s second

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

int i,j,n,m,v[100010],sol[100010],ans,ld,st,k;
pair< int , pair< int , int > >arb[4*100010];
pair<int,int> norm[100010];

void query( int nod, int left, int right, int pozMax, int lim )
{
    int middle = ( left + right ) / 2;

    if( left > lim ) return; ///DACA AM IESIT CU INTERVALUL IN DREAPTA LIMITEI
    if( arb[ nod ].f < ans ) return; ///NU MA INTERESEAZA ACEST INTERVAL

    if( right < lim )  ///SUNT IN INTERIOR
    {
        if( arb[ nod ].s.s < pozMax && v[ arb[ nod ].s.s ] < v[ norm[ i ].s ] )
        {
            if( arb[ nod ].f > ans )
            {
                ans = arb[ nod ].f;
                k = max( ans + 1 , k );
                sol[ pozMax ] = arb[ nod ].s.s;
                return;
            }
        }

        if( left == right )
            return;

        if( arb[ 2 * nod ].s.f < pozMax )///INTERVALUL DIN STANGA REPREZINTA UN PUNCT DE INTERES
            query( 2 * nod , left , middle , pozMax , lim );
        if( arb[ 2 * nod + 1 ].s.f < pozMax )///INTERVALUL DIN DREAPTA REPREZINTA UN INTERVAL DE INTERES
            query( 2 * nod + 1 , middle + 1 , right , pozMax , lim );
        return;
    }

    if( left == right )
        return;

    query( 2 * nod , left , middle , pozMax , lim);
    if( middle + 1 < lim )
        query( 2 * nod + 1 , middle + 1 , right , pozMax , lim );

}

void update( int nod, int left, int right, int src, int up )
{
    if( left == right && left == src )
    {
        arb[ nod ] = make_pair( up , make_pair( norm[ i ].s , norm[ i ].s ) );
        if( up == k )
            st = left;
        return;
    }

    if( left <= src && src <= right )
    {
        int middle = ( left + right ) / 2;
        update( 2 * nod , left , middle , src , up );
        update( 2 * nod + 1 , middle + 1 , right , src , up );

        if( arb[ 2 * nod ].f > arb[ 2 * nod + 1 ].f )
            arb[ nod ] = arb[ 2 * nod ];
        else
            arb[ nod ] = arb[ 2 * nod + 1 ];
        arb[ nod ].s.f = min( arb[ 2 * nod ].s.f , arb[ 2 * nod + 1 ].s.f );
    }
}

void afis( int k )
{
    if( k == 0 )
        return;
    afis( sol[ k ] );
    fout<<v[ k ]<<' ';
}

int main()
{
    fin>>n;
    for( i = 1 ; i <= n ; i++ )
    {
        fin>>v[ i ];
        norm[ i ] = make_pair( v[ i ] , i );
    }

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

    for( i = 1 ; i <= n ; i++ )
    {
        ld = norm[ i ].s;
        ans = 0;
        query( 1 , 1 , n , ld , i );
        update( 1 , 1 , n , i , ans + 1 );
    }
    fout<<arb[1].f<<'\n';
    //afis( st );

return 0;
}