Cod sursa(job #1759404)

Utilizator sulzandreiandrei sulzandrei Data 19 septembrie 2016 03:27:30
Problema Hashuri Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 11.41 kb

#include <iostream>
#include <fstream>

#include <set>

#include <algorithm>
#include <cmath>
#include <limits>
#include <ctime>
#include <cstdio>
#include <cstdlib>

using namespace std;

//std::ifstream in("algsort.in");
//std::ofstream out("algsort.out");

std::ifstream hin("hashuri.in");
std::ofstream hout("hashuri.out");;
class RBT
{
public:
    RBT(){init();};
    const bool RED = 1,BLACK = 0;
    struct node
    {
        int key;
        unsigned color:1;
        node* left, *right,*parent;
        node(int k,bool c, node* lt, node* rt,node* pt):key{k},color{c},left{lt},right{rt},parent{pt}{};
    };
    node *root ,* nil;
    void init()
    {
        root = nullptr;
        nil = new node(0,BLACK,nullptr,nullptr,nullptr);
    }
    bool search(int key,node* root)
    {
        if(root == nullptr || root == nil)
            return false;
        else if(key <root->key)
            return search(key,root->left);
        else if(key>root->key)
            return search(key,root->right);
        else
            return true;
    }
    void insert(int key,node* &root,node* parent)
    {
        if(root == nullptr)
        {
            root = new node(key,BLACK,nil,nil,parent);
            insert_case1(root);
        }
        else if( root == nil)
        {
            root = new node(key,RED,nil,nil,parent);
            insert_case1(root);
        }
        else if( key <= root->key)
            insert(key,root->left,root);
        else if( key > root->key)
            insert(key,root->right,root);

    }
    node *grandparent(struct node *n)
    {
        if ((n != nullptr) && (n->parent != nullptr))
            return n->parent->parent;
        return nullptr;
    }
    node *uncle(struct node *n)//unchiul nodului n
    {
        node *g = grandparent(n);
        if (g == nullptr)
            return nullptr; // No grandparent means no uncle
        if (n->parent == g->left)
            return g->right;
        else
            return g->left;
    }
    void leftRotate(node* &T,node * x)
    {
        node * y = x->right;
        x->right = y->left;
        if(y->left != nil)
            y->left->parent = x;
        y->parent = x->parent;
        if(x->parent == nullptr)
            T = y;
        else
        {
            if(x == x->parent->left)
                x->parent->left = y;
            else
                x->parent->right = y;
        }
        y->left =x;
        x->parent =y;

    }
    void rightRotate(node* &T,node* y) //rotim la dreapta
    {
        node* x = y->left;
        y->left = x->right;
        if(x->right != nil)
            x->right->parent = y;
        x->parent = y->parent;
        if(y->parent == nullptr)
            T = x;
        else
        {
            if(y->parent->left == y)
                y->parent->left = x;
            else
                y->parent->right = x;
        }
        x->right = y;
        y->parent = x;
    }
    void insert_case1(node *n) //caz radacina deci doar o coloram negru
    {
        if (n->parent == nullptr)
            n->color = BLACK;
        else
            insert_case2(n);
    }
    void insert_case2(node *n)//caz cand
    {
        if (n->parent->color == BLACK)
            return; /* Tree is still valid */
        else
            insert_case3(n);//altfel
    }
    void insert_case3(node *n)
    {

        node *u = uncle(n), *g;
        if ((u != nullptr) && (u->color == RED))
        {
            n->parent->color = BLACK;
            u->color = BLACK;
            g = grandparent(n);
            g->color = RED;
            insert_case1(g);
        }
        else
            insert_case4(n);
    }
    void insert_case4(node *n)
    {
        node *g = grandparent(n);
        if ((n == n->parent->right) && (n->parent == g->left))
        {
            leftRotate(root,n->parent);
            n = n->left;
        }
        else if ((n == n->parent->left) && (n->parent == g->right))
        {
            rightRotate(root,n->parent);
            n = n->right;
        }
        insert_case5(n);
    }
    void insert_case5(node *n)
    {
        node *g = grandparent(n);

        n->parent->color = BLACK;
        g->color = RED;

        if (n == n->parent->left)
            rightRotate(root,g);
        else
            leftRotate(root,g);
    }
    node *sibling(node *n)
    {
        if ((n == nullptr) || (n->parent == nullptr))
            return nullptr;
        if (n == n->parent->left)
            return n->parent->right;
        else
            return n->parent->left;
    }
    node* getMin(node* root)
    {
        if(root == nullptr)
            return root;
        return ( root->left == nil ) ? root : getMin( root->left );
    }
    node* getMax(node* root)
    {
        if(root == nullptr)
            return root;
        return(root->right == nil)?root: getMax(root->right);
    }
    void remove(int &key, node* &root)
    {
        if(root == nil)
            return;
        else if(key < root->key)
                remove(key,root->left);
        else if(key > root->key)
                remove(key,root->right);
        else if(root->left != nil && root->right != nil)
        {
            root->key = getMax(root->left)->key;
            remove(root->key,root->left);
        }
        else
            delete_one_child(root);
    }
    bool is_leaf(node* n)
    {
        return (n->right == nullptr && n->left == nullptr);
    }
    void replace_node(node* a, node *b)
    {
        node* p = a->parent;
        (p->left == a)? p->left = b : p->right = b;
        b->parent = p;
    }
    void delete_one_child(node *n)
    {
        node *child = is_leaf(n->right) ? n->left : n->right;

        replace_node(n, child);
        if (n->color == BLACK)
        {
            if (child->color == RED)
                child->color = BLACK;
            else
                delete_case1(child);
        }
        delete n;
    }
    void insert(int x)
    {
        insert(x,root,nullptr);
    }
    //functii extra
    void show(node* x)
    {
        if(x!= nil)
        {
            cout<<x->key<<" ";
            if (x->color == BLACK)
                cout<<"BLACK";
            else cout<< "RED";
            cout<<" si are copii pe : "<<x->left->key <<" && "<<x->right->key<<" ;";
            show(x->left);
            show(x->right);
        }
    }
    void delete_case1(node *n)
    {
        if (n->parent != nullptr)
            delete_case2(n);
    }
    void delete_case2(node *n)
    {
        node *s = sibling(n);

        if (s->color == RED)
        {
            n->parent->color = RED;
            s->color = BLACK;
            if (n == n->parent->left)
                leftRotate(root,n->parent);
            else
                rightRotate(root,n->parent);
        }
        delete_case3(n);
    }
    void delete_case3(node *n)
    {
        node *s = sibling(n);

        if ((n->parent->color == BLACK) &&
            (s->color ==  BLACK)        &&
            (s->left->color == BLACK)   &&
            (s->right->color == BLACK))
        {
            s->color = RED;
            delete_case1(n->parent);
        }
        else
            delete_case4(n);
    }
    void delete_case4(node *n)
    {
        node *s = sibling(n);

        if ((n->parent->color == RED) &&
         (s->color == BLACK)          &&
         (s->left->color == BLACK)    &&
         (s->right->color == BLACK))
        {
            s->color = RED;
            n->parent->color = BLACK;
        }
        else
            delete_case5(n);
    }
    void delete_case5(node *n)
    {
        node *s = sibling(n);

        if  (s->color == BLACK)
        {
            /* this if statement is trivial,
            due to case 2 (even though case 2 changed the sibling to a sibling's child,
            the sibling's child can't be red, since no red parent can have a red child). */
            /* the following statements just force the red to be on the left of the left of the parent,
            or right of the right, so case six will rotate correctly. */
            if ((n == n->parent->left) &&
              (s->right->color == BLACK) &&
              (s->left->color == RED))
            { /* this last test is trivial too due to cases 2-4. */
                s->color = RED;
                s->left->color = BLACK;
                rightRotate(root,s);
            }
            else if ((n == n->parent->right) &&
                     (s->left->color == BLACK) &&
                     (s->right->color == RED))
            {/* this last test is trivial too due to cases 2-4. */
                s->color = RED;
                s->right->color = BLACK;
                leftRotate(root,s);
            }
        }
        delete_case6(n);
    }
    void delete_case6(node *n)
    {
        node *s = sibling(n);

         s->color = n->parent->color;
         n->parent->color = BLACK;

        if (n == n->parent->left)
        {
            s->right->color = BLACK;
            leftRotate(root,n->parent);
        }
        else
        {
            s->left->color = BLACK;
            rightRotate(root,n->parent);
        }
    }
    bool search(int x)
    {
        return search(x,root);
    }
    void remove(int x)
    {
        if(search(x))
            remove(x,root);
    }
    void srd(node*root)
    {
        if(root!= nil)
        {
            cout<<"{ "<<root->key<<"  ";
            if(root->color== 0)
                cout<<"BLACK ";
            else
                cout<<"RED ";
            cout<<" {"<<root->left->key<<" , "<<root->right->key<<" }\n";
            srd(root->left);
            //out<<root->key<<" ";
            srd(root->right);
        }
    }
    void showSorted()
    {
        srd(root);
    }
};

//functia unde testam operatiile
//BST bst;
//AVL avl;
//Treap treap;
//set<int> um;
RBT rbt;
int main()
{
    int n,x,op,nr,nr2,j=0;
    hin >> n;
    for(int i = 0  ; i< n ; i++)
    {
        hin >> op >> x;
        //in >>x;
        switch(op)
        {
            case 1:
                rbt.insert(x);
                //treap.insert(x);
                //avl.insert(x);
                //bst.insert(x);
                  //  um.insert(x);
               break;
            case 2:
                //cout<<"\ninainte ca "<<x<<" sa fie sters\n";
                //rbt.showSorted();
                rbt.remove(x);
                //cout<<"\ndupa ce "<<x<<"a fost sters\n";
                //rbt.showSorted();

                //treap.erase(x);
                //um.erase(x);
                //bst.erase(x);
                //avl.remove(x);
             break;
            case 3:
                 nr = rbt.search(x);
                //nr = treap.find(x);
                //nr = avl.find(x);
                //nr = bst.find(x);
            //nr2 = (um.find(x)!=um.end())?1:0;
            hout<<nr<<'\n';
            //ing>> nr2;
            //j++;
            //if(nr != nr2)
              //  cout<<"linia "<<j<<" "<<nr<<"!="<<nr2<<"elementul "<<x<<'\n';
            break;
        }
        //rbt.insert(x);
        //avl.insert(x);
        //treap.insert(x);
        //bst.insert(x);
    }
    //rbt.showSorted();
    //avl.showSorted();
    //treap.showSorted();
    //bst.showSorted();z
}