Cod sursa(job #1252946)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 31 octombrie 2014 16:59:06
Problema Zeap Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 11.42 kb
#include <fstream>
#include <cstring>
#include <iostream>

using namespace std;


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

template <class TEMPLATE>
class AVL;

template <class TEMPLATE> // needs ==, < and > operators
class node
{
    node <TEMPLATE> *left,*right;
    int balance, subtree, maxdepth;

    //RECALCULATIONS

    void get_maxdepth ()
    {
         maxdepth = 0;

         if (left != NULL)
           maxdepth = max (maxdepth,left->maxdepth+1);
         if (right != NULL)
           maxdepth = max (maxdepth,right->maxdepth+1);
     }

     void get_subtree ()
     {
         subtree = count;

         if (left != NULL)
           subtree += left->subtree;
         if (right != NULL)
           subtree += right->subtree;
     }

     void get_balance ()
     {
         if (left != NULL && right != NULL)
            balance = left->maxdepth - right->maxdepth;
         else if (left != NULL)
            balance = left->maxdepth+1;
         else if (right != NULL)
            balance = -right->maxdepth-1;
         else balance = 0;
     }

     void recalculate ()
     {
         get_maxdepth();
         get_subtree();
         get_balance ();
     }

    public:
    TEMPLATE data;
    int count;

    friend class AVL<TEMPLATE>;
};

template <class TEMPLATE>
class AVL
{
     node <TEMPLATE> *root/*root of the tree*/, *current /*pointer used to store temporary node*/;
     TEMPLATE search_value /*used to store temporary search value*/, bad_signal /*value chosen upon declaration to signal that a given operation is invalid*/;
     int nr_objects /*number of elements in tree*/, to_erase /*number of elements to erase*/;

     public:

     //size function
     int size ()
     {
        return nr_objects;
     }

     //CONSTRUCTOR

     AVL (TEMPLATE bs = 0)
     {
         root = NULL;
         nr_objects = 0;
         bad_signal = bs;
     }

     //DESTRUCTOR

     void destroy (node <TEMPLATE> *T)
     {
         if (T->left != NULL)
            destroy (T->left);
        if (T->right != NULL)
            destroy (T->right);
        delete T;
     }

     ~AVL ()
     {
         if (root != NULL)
             destroy (root);
     }

     //BALANCE

     private:

     node <TEMPLATE> *rotate_left (node <TEMPLATE> * T)
     {
         node <TEMPLATE> *save = T->right;
         T->right = save->left;
         save->left = T;

         T->recalculate();
         save->recalculate();

         return save;
     }

     node <TEMPLATE> *rotate_right (node <TEMPLATE> * T)
     {
         node <TEMPLATE> *save = T->left;
         T->left = save->right;
         save->right = T;

         T->recalculate();
         save->recalculate();

         return save;
     }

     node <TEMPLATE> *repair (node <TEMPLATE> *T)
     {
         T->recalculate();

         if (T->balance == 2)
         {
             if (T->left->balance < 0)
             {
                 T->left = rotate_left (T->left);
             }
             T = rotate_right (T);
         }
         else if (T->balance == -2)
         {
             if (T->right->balance > 0)
             {
                 T->right = rotate_right (T->right);
             }
             T = rotate_left (T);
         }

         return T;
     }


     //INSERTION

     private:

     node<TEMPLATE> *recursive_insert (node <TEMPLATE> *T)
     {
         if (T == NULL)
           return current;
         else if (current->data == T->data)
         {
             T->count += current->count;
         }
         else if (current->data < T->data)
         {
             T->left = recursive_insert(T->left);
         }
         else
         {
             T->right = recursive_insert (T->right);
         }

         T = repair (T);
         return T;
     }

     public:

     void insert (TEMPLATE ins)
     {
         current = new node<TEMPLATE>;
         current->data = ins;
         current->left = NULL;
         current->right = NULL;
         current->balance = 0;
         current->maxdepth = 0;
         current->subtree = 1;
         current->count = 1;

         root = recursive_insert(root);
         ++nr_objects;
     }

     //SEARCH

     private:

     node <TEMPLATE> *search (node <TEMPLATE> *T)
     {
         if (T==NULL)
           return NULL;
         else if (search_value == T->data)
           return T;
         else if (search_value < T->data)
           return search (T->left);
         else return search (T->right);
     }

     public:

     int find (TEMPLATE x)
     {
         search_value = x;
         current =  search (root);

         if (current == NULL)
           return 0;
         return current->count;
     }

     //NEXT/PREV

     private:

     node<TEMPLATE> *get_next (node <TEMPLATE> *T)
     {
         if (T == NULL)
           return NULL;
         else if (T->data > search_value)
         {
             current = get_next (T->left);
             if (current == NULL)
                return T;
             else return current;
         }
         else
         {
             return get_next (T->right);
         }
     }

     node<TEMPLATE> *get_prev (node <TEMPLATE> *T)
     {
         if (T == NULL)
           return NULL;
         if (T->data < search_value)
         {
             current = get_prev (T->right);
             if (current == NULL)
               return T;
             else return current;
         }
         else
         {
             return get_prev (T->left);
         }
     }

     public:

     TEMPLATE next (TEMPLATE x)
     {
         search_value = x;
         current =  get_next (root);

         if (current == NULL)
           return bad_signal;
         else return current->data;
     }

     TEMPLATE prev (TEMPLATE x)
     {
         search_value = x;
         current = get_prev (root);

         if (current == NULL)
           return bad_signal;
         else return current->data;
     }

     //MIN/MAX

     private:

     node <TEMPLATE> *get_min (node <TEMPLATE> *T)
     {
         if (T->left == NULL)
           return T;
        return get_min(T->left);
     }

     node <TEMPLATE> *get_max (node <TEMPLATE> *T)
     {
         if (T->right == NULL)
           return T;
        return get_max(T->right);
     }

     public:

     TEMPLATE min ()
     {
         if (nr_objects == 0)
           return bad_signal;

         current = get_min (root);
         return current->data;
     }

     TEMPLATE max ()
     {
         if (nr_objects == 0)
           return bad_signal;

         current = get_max (root);
         return current->data;
     }

     //DELETION

     private:

     node <TEMPLATE> *recursive_erase (node <TEMPLATE> *T)
     {
         if (T == NULL)
           return T;
         else if (search_value == T->data)
         {
             if (T->count)
             {
                T->count -= to_erase;
                nr_objects -= to_erase;
             }

             if (T->count == 0)
             {
                 if (T->left == NULL && T->right == NULL)
                 {
                     delete T;
                     return NULL;
                 }
                 else if (T->right == NULL)
                 {
                     current = T->left;
                     delete T;
                     T = current;
                 }
                 else if (T->left == NULL)
                 {
                     current = T->right;
                     delete T;
                     T = current;
                 }
                 else
                 {
                     current = get_max (T->left);  //replace the node with the maximum on the left or the minimum on the right and then erase that node
                     T->data = current->data;
                     T->count = current->count;

                     current->count = 0;
                     search_value = current->data;

                     T->left = recursive_erase (T->left);
                 }
             }
         }
         else if (search_value < T->data)
         {
             T->left = recursive_erase (T->left);
         }
         else
         {
             T->right = recursive_erase (T->right);
         }

         T = repair (T);
         return T;
     }

     public:

     void erase (TEMPLATE er)
     {
         search_value = er;
         to_erase = 1;
         root = recursive_erase (root);
     }

     //Kth ELEMENT

     private:

     node<TEMPLATE> *get_kth_element (node <TEMPLATE> *T)
     {
         int leftsub = 0;
         if (T->left != NULL)
           leftsub = T->left->subtree;

        if (leftsub == search_value-1)
            return T;
        else if (leftsub > search_value-1)
            return get_kth_element (T->left);
        else
        {
            search_value -= leftsub+1;
            return get_kth_element (T->right);
        }
     }

     public:

     TEMPLATE kth_element (int k)
     {
         if (k > nr_objects)
           return bad_signal;

         search_value = k;

         return get_kth_element (root) -> data;
     }
};

char s[1<<22];
int p,n,x,y,op,z;

int get_op ()
{
    p+=2;
    if (s[p-1] == 'I')
       return 1;
    if (s[p-1] == 'S')
       return 2;
    if (s[p-1] == 'C')
       return 3;
    p +=2;
    if (s[p-2] == 'A')
       return 4;
    if (s[p-2] == 'I')
       return 5;
    return 6;
}

int get_int()
{
    ++p;

    int x = 0;

    while (p < n && s[p] != ' ' && s[p] != '\n')
    {
        x = x*10+(s[p]-'0');
        ++p;
    }
    return x;
}

int main()
{
    FILE *file = fopen ("zeap.in","r");
    fread (s,1,(1<<22),file);
    n = strlen(s);

    AVL <int> S,dif;
    p = -1;

    while (p < n)
    {
        op = get_op ();
        if (op == 6)
         break;

        if (op == 1)
        {
            x = get_int ();

            if (S.find(x))
              continue;
            S.insert (x);

            y = S.next (x);
            if (y != 0)
              dif.insert (y-x);
            z = S.prev (x);
            if (z != 0)
               dif.insert (x-z);
            if (y != 0 && z != 0)
               dif.erase (y-z);
        }
        else if (op == 2)
        {
            x = get_int ();

            if (!S.find (x))
                fout<<-1<<"\n";
            else
            {
                y = S.next (x);
                if (y != 0)
                  dif.erase (y-x);
                z = S.prev (x);
                if (z != 0)
                  dif.erase (x-z);
                if (y != 0 && z != 0)
                  dif.insert (y-z);
                S.erase (x);
            }
        }
        else if (op == 3)
        {
            x = get_int();

            y = S.find (x);

            if (y)
              fout<<1;
            else fout<<0;
            fout<<"\n";
        }
        else if (op == 4)
        {
            if (S.size() < 2)
            {
                fout<<-1<<"\n";
            }
            else fout<<S.max()-S.min()<<"\n";
        }
        else
        {
            if (S.size() < 2)
            {
                fout<<-1<<"\n";
            }
            else fout<<dif.min()<<"\n";
        }
    }
}