Cod sursa(job #1276471)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 26 noiembrie 2014 14:26:46
Problema Heapuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 10.98 kb
#include <iostream>
#include <fstream>

using namespace std;

template <class type> class AVL;
template <class type> class node;

template <class type> class node
{
    // *left    adresa catre fiul stang
    // *right   adresa catre fiul drept
    // data     informatia din nod
    // count    cate valori egale cu data exista in AVL
    // balance  diferenta dintre inaltimea subarborelui stang si inaltimea subarborelui drept
    // height   inaltimea subarborelui cu radacina in obiectul curent
    // weight   greutatea subarborelui cu radacina in obiectul curent i.e. suma tuturor count-urilor din subarborele curent
    public: type data;

    private:
    node <type> *left, *right;
    int count, balance, height, weight;

    void UpdateBalance()
    {
        this -> balance = 0;
        if (this->left != NULL && this->right != NULL)
        {
            this->balance = this->left->height - this->right->height;
            return ;
        }
        if (this->left != NULL)
        {
            this->balance = this->left->height + 1;
            return ;
        }
        if (this->right != NULL)
        {
            this->balance = -(this->right->height + 1);
            return ;
        }
    }
    void UpdateHeight()
    {
        this->height = 0;
        if (this->left != NULL)
            this->height = max(this->height, this->left->height + 1);
        if (this->right != NULL)
            this->height = max(this->height, this->right->height + 1);
    }
    void UpdateWeight()
    {
        this->weight = 0;
        if (this->left != NULL)
            this->weight += this->left->weight;
        if (this->right != NULL)
            this->weight += this->right->weight;
        this->weight += this->count;
    }
    void UpdateAll()
    {
        UpdateWeight();
        UpdateHeight();
        UpdateBalance();
    }
    public : node <type> (const type _newdata, const int _newcount)
    {
        this -> data = _newdata;
        this -> count = _newcount;
        this -> weight = _newcount; /// !!!
        this -> balance = 0;
        this -> height = 0;
        this -> left = this -> right = NULL;
    }
    friend class AVL<type>;
};

template <class type> class AVL
{
    private:
    node <type> *root, *now, *save;
    type searchdata, error;
    int total_count, to_erase;
    bool success;
    public: AVL(const type error)
    {
        /// TODO de definit ce inseamna eroare
        /// DONE.
        this->error = error;
        root = NULL;
        this->total_count = 0;
    }

    public: AVL()
    {
        /// TODO de definit ce inseamna eroare
        /// DONE.
        this->error = 0;
        root = NULL;
        this->total_count = 0;
    }
    public: inline int Size()
    {
        return this -> total_count;
    }

    private: node <type> *RotateLeft(node <type> *r)
    {
        save = r -> right;
        r -> right = save -> left;
        r -> UpdateAll();
        save -> left = r;
        save -> UpdateAll();
        return save;
    }

    private: node <type> *RotateRight(node <type> *r)
    {
        save = r -> left;
        r -> left = save -> right;
        r -> UpdateAll();
        save -> right = r;
        save -> UpdateAll();
        return save;
    }

    private: node <type> *balance(node <type> *r)
    {
        /// TO DO
        /// DONE.
        r -> UpdateAll();
        if (r -> balance == 2)
        {
            if (r -> left -> balance == -1)
                r->left = RotateLeft(r->left);
            r = RotateRight(r);
        }
        if (r->balance == -2)
        {
            if (r -> right -> balance == 1)
                r->right = RotateRight(r->right);
            r = RotateLeft(r);
        }
        r -> UpdateAll();
        return r;
    }

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

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

    // min
    // max

    private: node <type> *min(node <type> *r)
    {
        if (r->left == NULL)
            return r;
        return min(r->left);
    }

    private: node <type> *max(node <type> *r)
    {
        if (r->right == NULL)
            return r;
        return max(r->right);
    }

    public: type min()
    {
        if (this->total_count == 0)
            return error;
        now = min(root);
        return now->data;
    }

    public: type max()
    {
        if (this->total_count == 0)
            return error;
        now = max(root);
        return now->data;
    }

    // prev
    // next

    private: node <type> *prev(node <type> *r)
    {
        if (r == NULL)
            return NULL;
        if (!(r->data < searchdata))
            return prev(r->left);
        else
        {
            now = pred(r->right);
            if (now == NULL)
                return r;
            return now;
        }
    }

    private: node <type> *next(node <type> *r)
    {
        if (r == NULL)
            return NULL;
        if (!(r->data > searchdata))
            return next(r->right);
        else
        {
            now = next(r->left);
            if (now == NULL)
                return r;
            return now;
        }
    }

    public: type prev(const type _newsearchdata) // the greatest value smaller than _newsearchdata
    {
        searchdata = _newsearchdata;
        now = pred(root);
        if (now == NULL)
            return error;
        return now -> data;
    }

    public: type next(const type _newsearchdata) // the smallest value greater than _newsearchdata
    {
        searchdata = _newsearchdata;
        now = next(root);
        if (now == NULL)
            return error;
        return now -> data;
    }


    /// insert

    private: node <type> *Insert(node<type> *r) // insert now-node in the r-subtree
    {   // insereaza nodul now in subarborele lui r si returneaza o adresa catre radacina arborelui dupa balance
        if (r == NULL)
            return now;
        else if (r->data == now->data)
            r->count += now->count;
        else if (r->data > now->data)
            r->left = Insert(r->left);
        else
            r->right = Insert(r->right);
        r = balance(r);
        return r;
    }
    public: void Insert(const type _newdata)
    {
        now = new node <type> (_newdata, 1);
        ++ this->total_count;
        root = Insert(root);
    }
    public: void Insert(const type _newdata, const int _newcount)
    {
        now = new node <type> (_newdata, _newcount);
        ++ this->total_count;
        root = Insert(root);
    }

    /// find

    private: node <type> *Find(const node <type> *r)
    {
        if (r == NULL)
            return NULL;
        if (r->data == searchdata)
            return r;
        if (r->data > searchdata)
            return Find(r->left);
        return Find(r->right);
    }
    public: int Find(const type _newsearch)
    {
        searchdata = _newsearch;
        now = Find(root);
        if (now == NULL)
            return 0;
        return now -> count;
    }

    /// erase

    private: node <type> *Erase(node <type> *r)
    {
        if (r == NULL)
        {
            success = false;
            return r;
        }
        if (r->data == searchdata)
        {
            if (r->count >= to_erase) /// !!!
            {
                success = true;
                r->count -= to_erase;
                this->total_count -= to_erase;
                if (r->count == 0)
                {
                    if (r->left == NULL && r->right == NULL)
                    {
                        delete r;
                        return NULL;
                    }
                    else if (r->left == NULL) /// !!!
                    {
                        now = r->right;
                        delete r;
                        r = now;
                    }
                    else if (r->right == NULL)
                    {
                        now = r->left;
                        delete r;
                        r = now;
                    }
                    else
                    {
                        now = max(r->left);
                        r->count = now->count;
                        r->data = now->data;

                        now->count = 0;
                        searchdata = now->data;
                        to_erase = 0; /// !!!

                        r->left = Erase(r->left);
                    }
                }
            }
            else
            {
                success = false;
            }
        }
        else
            if (r->data > searchdata)
                r->left = Erase(r->left);
            else
                r->right = Erase(r->right);
        r = balance(r);
        return r;
    }
    // returns true whether i was able to delete an appearance of the data receieved and false whether not
    public: bool Erase(const type _erasedata)
    {
        success = false;
        searchdata = _erasedata;
        to_erase = 1;
        root = Erase(root);
        return success;
    }
    // returns true whether i was able to delete _erase_amount appearances of the data received and false whether not
    public: bool Erase(const type _erasedata, const int _erase_amount)
    {
        success = false;
        searchdata = _erasedata;
        to_erase = _erase_amount;
        root = Erase(root);
        return success;
    }

    // nth_element

    private: node <type> *nth_element(node <type> *r, int k)
    {
        int left_subtree = 0;
        if (r -> left)
            left_subtree = r->left->weight;
        if (left_subtree >= k)
            return (r->left, k);
        else if (left_subtree < k)
        {
            k = k - left_subtree;
            if (k <= r->count)
                return r->data;
            return nth_element(r->right, k - r->count);
        }
    }

    public: type nth_element(const int k)
    {
        if (k < 1 || k > total_count)
            return error;

        now = nth_element(root, k); /// !!!
        return now -> data;
    }
};

const int NMax = 200010;
int a[NMax];
int na, N;
AVL <int> s;

int main()
{
    ifstream f ("heapuri.in");
    ofstream g ("heapuri.out");
    f >> N;
    int x;
    for (int i = 1; i <= N; ++ i)
    {
        int op; f >> op;
        switch (op)
        {
            case 1:
                f >> x;
                a[++na] = x;
                s.Insert(x);
            break;
            case 2:
                f >> x;
                s.Erase(a[x]);
            break;
            case 3:
                g << s.min() << "\n";
            break;
        }
    }
    f.close();
    g.close();

    return 0;
}