Cod sursa(job #980177)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 4 august 2013 12:07:25
Problema Zeap Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.88 kb
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <string>

using namespace std;

class Treap
{
    private:

        class Node
        {
            public:

                const int infinity = int(1e9);

                int key;
                int priority;
                int minim;
                int maxim;
                int min_diff;

                Node *left, *right;

                Node( int _key );

                void update( );
        };

        void insert( Node *&, Node *& );
        void erase( Node *&, int );
        int find( Node *, int );
        void spin_left( Node *& );
        void spin_right( Node *& );
        void balance( Node *& );

    public:

        Node *R;

        Treap(): R( NULL )
        {
            srand( time( NULL ) );
        }

        void insert( int );
        int erase( int );
        int find( int );
        int max_diff( );
        int min_diff( );
        void update( Node *& );
};

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

    Treap T;
    string s;
    int key;

    while( f >> s )
    {
        if ( s == "I" )
        {
            f >> key;
            T.insert( key );
            continue;
        }

        if ( s == "S" )
        {
            f >> key;
            if ( !T.erase( key ) )
                    g << "-1\n";
            continue;
        }

        if ( s == "C" )
        {
            f >> key;
            g << T.find( key ) << "\n";
            continue;
        }

        if ( s == "MIN" )
        {
            g << T.min_diff() << "\n";
            continue;
        }

        if ( s == "MAX" )
        {
            g << T.max_diff() << "\n";
            continue;
        }
    }

    return 0;
}

Treap::Node::Node( int _key )
{
    key = _key;
    priority = rand() + 1;
    minim = _key;
    maxim = _key;
    min_diff = infinity;
    left = NULL;
    right = NULL;
}

void Treap::Node::update()
{
    minim = maxim = key;

    if ( left )
            maxim = max( maxim, left->maxim ),
            minim = min( minim, left->minim );

    if ( right )
            maxim = max( maxim, right->maxim ),
            minim = min( minim, right->minim );

    min_diff = infinity;

    if ( left )
            min_diff = min( min_diff, left->min_diff ),
            min_diff = min( min_diff, key - left->maxim );

    if ( right )
            min_diff = min( min_diff, right->min_diff ),
            min_diff = min( min_diff, right->minim - key );

}

void Treap::insert( Node *&n, Node *&p )
{
    if ( n == NULL )
    {
        n = p;
        return;
    }

    if ( p->key < n->key )
            insert( n->left, p );
    else
        if ( p->key > n->key )
            insert( n->right, p );

    balance( n );
}

void Treap::erase( Node *&n, int key )
{
    if ( key < n->key )
            erase( n->left, key );
    else
        if ( key > n->key )
                erase( n->right, key );
    else
    {
        int cache = ( ( n->left ) ? 1 : 0 ) + ( ( n->right ) ? 1 : 0 );

        if ( cache == 2 )
            ( n->left->priority > n->right->priority ) ? spin_left(n) : spin_right(n);
        else
            if ( cache == 1 )
                ( n->left ) ? spin_left(n) : spin_right(n);
        else
            delete n, n = NULL;

        if ( n != NULL )
                erase( n, key );
    }

    if ( n != NULL )
            update( n );
}

int Treap::find( Node *n, int key )
{
    if ( n == NULL )      return 0;
    if ( n->key == key )  return 1;
    if ( n->key > key )   find( n->left, key );
    if ( n->key < key )   find( n->right, key );

    return 0;
}

void Treap::spin_left( Node *&n )
{
    Node *p = n->left;
    n->left = p->right;
    p->right = n;
    update( n );
    update( p );
    n = p;
}

void Treap::spin_right( Node *&n )
{
    Node *p = n->right;
    n->right = p->left;
    p->left = n;
    update( n );
    update( p );
    n = p;
}

void Treap::balance( Node *&n )
{
    if ( n->left && n->priority < n->left->priority )
            spin_left( n );
    else
        if ( n->right && n->priority < n->right->priority )
            spin_right( n );

    update( n );
}

void Treap::insert( int key )
{
    Node *p = new Node(key);
    insert( R, p );
}

int Treap::erase( int key )
{
    if ( !find( R, key ) )  return 0;
    erase( R, key );
    return 1;
}

int Treap::find( int key )
{
    return find( R, key );
}

int Treap::max_diff()
{
    if ( !R || ( !R->left && !R->right ) )
            return -1;

    return R->maxim - R->minim;
}

int Treap::min_diff()
{
    if ( !R || ( !R->left && !R->right ) )
            return -1;

    return R->min_diff;
}

void Treap::update( Node *&n )
{
    n->update();
}