Cod sursa(job #1276547)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 26 noiembrie 2014 15:57:38
Problema Zeap Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 13.62 kb
#include <fstream>
#include <algorithm>
#define ch buffer[position]
#define Next (++position == limit) ? (fread(buffer, 1, limit, f), position = 0) : 0

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()
    {
        /// TODO de definit ce inseamna eroare
        /// DONE.
        this->error = 0;
        root = NULL;
        this->total_count = 0;
    }
    public: AVL(const type error)
    {
        /// TODO de definit ce inseamna eroare
        /// DONE.
        this->error = error;
        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;
    }

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

    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 = prev(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 = prev(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(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;
    }
};


AVL <int> S, diff;
FILE *f = fopen("zeap.in", "r");
const int limit = 1024 * 1024;
int position;
char buffer[limit];

inline int GetNext(int & x)
{
    if (ch == '\n')
        Next;
    if (ch == 0)
        return -1;
    if (ch == 'I')
    {
        Next;
        Next;
        for (x = 0; '0' <= ch && ch <= '9'; x = x * 10 + ch - '0', Next);
        return 1;
    }
    if (ch == 'S')
    {
        Next;
        Next;
        for (x = 0; '0' <= ch && ch <= '9'; x = x * 10 + ch - '0', Next);
        return 2;
    }
    if (ch == 'C')
    {
        Next;
        Next;
        for (x = 0; '0' <= ch && ch <= '9'; x = x * 10 + ch - '0', Next);
        return 3;
    }
    if (ch == 'M')
    {
        Next;
        if (ch == 'A')
        {
            Next;
            Next;
            return 4;
        }
        Next;
        Next;
        return 5;
    }
    return -1;
}


int main()
{
    S = AVL <int> (-1);
    diff = AVL <int> (-1);
    FILE *g = fopen("zeap.out", "w");

    while (true)
    {
        int x;
        int op = GetNext(x);
        if (op == -1)
            break;
        if (op == 4)
        {
            int sz = S.Size();
            if (sz > 1)
                fprintf(g, "%d\n", S.max() - S.min());
            else
                fprintf(g, "-1\n");
        }
        else if (op == 5)
        {
            int sz = S.Size();
            if (sz > 1)
                fprintf (g, "%d\n", diff.min());
            else
                fprintf (g, "-1\n");
        }
        else if (op == 3)
        {
            // cauta
            fprintf (g, "%d\n", S.Find(x));
        }
        else if (op == 2)
        {
            /// de facut update la diff TODO
            // Sterge()
            bool success = S.Erase(x);
            if (!success)
                fprintf (g, "-1\n");
            else
            {
                int minim = S.prev(x);
                int maxim = S.next(x);
                if (minim == -1 && maxim == -1)
                    continue;
                else if (minim == -1)
                    diff.Erase(maxim - x);
                else if (maxim == -1)
                    diff.Erase(x - minim);
                else
                {
                    diff.Erase(x - minim);
                    diff.Erase(maxim - x);
                    diff.Insert(maxim - minim);
                }
            }
        }
        else
        {
            /// de facut update la diff TODO
            // Insert
            if (S.Find(x))
                continue;
            S.Insert(x); /// TODO de facut update la diff
            int minim = S.prev(x);
            int maxim = S.next(x);
            if (minim == -1 && maxim == -1)
                continue;
            else if (minim == -1)
                diff.Insert(maxim - x);
            else if (maxim == -1)
                diff.Insert(x - minim);
            else
            {
                diff.Erase(maxim - minim);
                diff.Insert(maxim - x);
                diff.Insert(x - minim);
            }
        }
    }
    fclose(f);
    fclose(g);
    return 0;
}