Cod sursa(job #1184891)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 14 mai 2014 14:22:44
Problema Secv8 Scor 25
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.47 kb
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>

using namespace std;

const int INF = 1 << 29;

struct Treap
{
    int key;
    int prior;
    int rev;
    int nr;
    Treap *st, *dr;

    Treap(){}

    Treap( int _k, int _p, int _r, int _nr, Treap *_st, Treap *_dr )
    {
        key = _k;
        prior = _p;
        rev = _r;
        nr = _nr;
        st = _st;
        dr = _dr;
    }

} *root, *NIL;

void initTreap()
{
    srand( time( NULL ) );
    NIL = new Treap( 0, 0, 0, 0, NULL, NULL );
    root = NIL;
}

void lazy( Treap *&T )
{
    if ( T != NIL && T->rev )
    {
        swap( T->st, T->dr );

        T->st->rev ^= 1;
        T->dr->rev ^= 1;
        T->rev = 0;
    }
}

void lz( Treap *&T )
{
    lazy( T );
    lazy( T->st );
    lazy( T->dr );
}

void update( Treap *&T )
{
    ///if ( T != NIL )
    {
        T->nr = 1 + T->st->nr + T->dr->nr;
        lz( T );
    }
}

void rol( Treap *&T )
{
    Treap *aux = T->st;
    T->st = aux->dr;
    aux->dr = T;

    update( aux );
    update( T );

    T = aux;
}

void ror( Treap *&T )
{
    Treap *aux = T->dr;
    T->dr = aux->st;
    aux->st = T;

    update( aux );
    update( T );

    T = aux;
}

void balance( Treap *&T )
{
    if ( T->st->prior > T->prior ) rol( T );
    if ( T->dr->prior > T->prior ) ror( T );

    update( T );
}

void insert( Treap *&T, int value, int pos, int p = rand() % INF + 1 )
{
    if ( T == NIL )
    {
        T = new Treap( value, p, 0, 1, NIL, NIL );
    }
    else
    {
        if ( pos <= T->st->nr + 1 )
                insert( T->st, value, pos, p );
        else
                insert( T->dr, value, pos - T->st->nr - 1, p );

        balance( T );
    }
}

void erase( Treap *&T, int pos )
{
    if ( T == NIL ) return;

    if ( pos <= T->st->nr )
            erase( T->st, pos );
    else
        if ( pos > T->st->nr + 1 )
                erase( T->dr, pos - T->st->nr - 1 );
        else
        {
            if ( T->st == NIL && T->dr == NIL )
            {
                delete T;
                T = NIL;
                return;
            }
            else
            {
                if ( T->st->prior > T->dr->prior )
                {
                    rol( T );
                    erase( T->dr, pos - T->st->nr - 1 );
                }
                else
                {
                    ror( T );
                    erase( T->st, pos );
                }
            }
        }

    if ( T != NIL ) update( T );
}

int kth_element( Treap *T, int pos )
{
    if ( T == NIL ) return -1;
    lz( T );
    if ( T->st->nr + 1 == pos ) return T->key;
    if ( pos <= T->st->nr ) return kth_element( T->st, pos );
    else                    return kth_element( T->dr, pos - T->st->nr - 1 );
}

void split( Treap *&T, Treap *&Ts, Treap *&Td, int pos )
{
    insert( T, 0, pos, INF );
    Ts = T->st;
    Td = T->dr;
    delete T;
    T = NIL;
}

void join( Treap *&T, Treap *&Ts, Treap *&Td )
{
    T = new Treap( 0, INF, 0, 0, Ts, Td );
    update( T );
    erase( T, T->st->nr + 1 );
}

void reverse( int i, int j )
{
    Treap *aux, *T1, *T2, *T3;

    split( root, aux, T3, j + 1 );
    split( aux, T1, T2, i );
    T2->rev = 1;
    join( aux, T1, T2 );
    join( root, aux, T3 );
}

void inorder( Treap *T, ostream &g )
{
    if ( T == NIL ) return;
    lz( T );
    inorder( T->st, g );
    g << T->key << " ";
    inorder( T->dr, g );
}

int main()
{
    ifstream f("secv8.in");
    ofstream g("secv8.out");

    srand( time( NULL ) );

    int N, rev, k, x, y;
    char oper;

    f >> N >> rev;

    initTreap();

    for (int i = 1; i <= N; ++i)
    {
        f >> oper;

        switch (oper)
        {
            case 'A':
            {
                f >> k;
                g << kth_element(root, k) << "\n";
                break;
            }
            case 'D':
            {
                f >> x >> y;
                for ( int j = x; j <= y; ++j ) erase(root, x);
                break;
            }
            case 'I':
            {
                f >> x >> y;
                insert(root, y, x);
                break;
            }
            case 'R':
            {
                f >> x >> y;
                reverse( x, y );
                break;
            }
        }
    }

    inorder(root, g);

    return 0;
}