Cod sursa(job #1479535)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 31 august 2015 16:13:44
Problema Secv8 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 9.71 kb
#include <bits/stdc++.h>

using namespace std;

class IndexableTreap ///1-based
{
private:

    static const int MAX_PRIORITY = 1000000000;

    class Node
    {
    public:

        int Key;
        size_t Size;
        bool Reverse;
        size_t Priority;

        int Sum;

        Node *Left, *Right;

        Node(const int k, const size_t nr, const bool rev, const size_t pr, Node *l, Node *r) : Key(k), Size(nr),
            Reverse(rev), Priority(pr), Sum(k), Left(l), Right(r) {
        }
    };

    void lazy_update(Node* &T)
    {
        if (T != NIL && T->Reverse == true)
        {
            T->Left->Reverse  ^= 1;
            T->Right->Reverse ^= 1;
            T->Reverse = false;

            swap(T->Left, T->Right);
        }
    }

    void update(Node* &T)
    {
        lazy_update(T);
        lazy_update(T->Left);
        lazy_update(T->Right);

        if (T != NIL)
        {
            T->Size = 1 + T->Left->Size + T->Right->Size;
            T->Sum = T->Key + T->Left->Sum + T->Right->Sum;
        }
    }

    Node* rotate_to_right(Node* &T)
    {
        assert(T != NIL);

        Node *tmp = T->Left;
        T->Left = tmp->Right;
        tmp->Right = T;

        update(T);
        update(tmp);

        return tmp;
    }

    Node* rotate_to_left(Node* &T)
    {
        assert(T != NIL);

        Node *tmp = T->Right;
        T->Right = tmp->Left;
        tmp->Left = T;

        update(T);
        update(tmp);

        return tmp;
    }

    void balance(Node* &T)
    {
        assert(T != NIL);

        if (T->Left->Priority > T->Priority)
            T = rotate_to_right(T);
        else if (T->Right->Priority > T->Priority)
                T = rotate_to_left(T);
        else
            update(T);
    }

    void insert_after(Node* &T, size_t position, const int key, const int priority)
    {
        if (T == NIL)
            T = new Node(key, 1, false, priority, NIL, NIL);
        else
        {
            lazy_update(T);
            lazy_update(T->Left);
            lazy_update(T->Right);

            if (position <= T->Left->Size)
                insert_after(T->Left, position, key, priority);
            else
                insert_after(T->Right, position - 1 - T->Left->Size, key, priority);

            balance(T);
        }
    }

    void change_key(Node* &T, size_t position, const int key)
    {
        assert(T != NIL);

        lazy_update(T);
        lazy_update(T->Left);
        lazy_update(T->Right);

        if (T->Left->Size + 1 == position)
        {
            T->Key = key;
            update(T);
        }
        else
        {
            if (position <= T->Left->Size)
                change_key(T->Left, position, key);
            else
                change_key(T->Right, position - 1 - T->Left->Size, key);
        }

        if (T != NIL)
            update(T);
    }

    int kth_element(Node* &T, size_t position)
    {
        assert(T != NIL);

        lazy_update(T);
        lazy_update(T->Left);
        lazy_update(T->Right);

        if (T->Left->Size + 1 == position)
            return T->Key;

        if (position <= T->Left->Size)
            return kth_element(T->Left, position);
        else
            return kth_element(T->Right, position - 1 - T->Left->Size);
    }

    void erase(Node* &T, size_t position)
    {
        if (T == NIL)
            return;

        lazy_update(T);
        lazy_update(T->Left);
        lazy_update(T->Right);

        if (position <= T->Left->Size)
            erase(T->Left, position);
        else if (position > T->Left->Size + 1)
            erase(T->Right, position - 1 - T->Left->Size);
        else
        {
            if (T->Left == NIL && T->Right == NIL)
            {
                delete T;
                T = NIL;
            }
            else
            {
                if (T->Left->Priority > T->Right->Priority)
                {
                    T = rotate_to_right(T);
                    erase(T->Right, position - 1 - T->Left->Size);
                }
                else
                {
                    T = rotate_to_left(T);
                    erase(T->Left, position);
                }
            }
        }

        if (T != NIL)
            update(T);
    }

    void split(Node* &T, Node* &L, Node* &R, const size_t position) ///splits in [1...position] and [position+1...treap.size()]
    {
        insert_after(T, position, 1, MAX_PRIORITY);
        L = T->Left;
        R = T->Right;

        delete T;
        T = NIL;
    }

    void join(Node* &T, Node* &L, Node* &R)
    {
        T = new Node(1, 1, false, MAX_PRIORITY, L, R);
        update(T);

        erase(T, T->Left->Size + 1);
    }

    void inorder(Node* &T, vector<int> &keys)
    {
        if (T == NIL)
            return;

        lazy_update(T);
        lazy_update(T->Left);
        lazy_update(T->Right);

        inorder(T->Left, keys);
        keys.push_back(T->Key);
        inorder(T->Right, keys);
    }

    void clear(Node* &T)
    {
        if (T == NIL)
            return;

        clear(T->Left);
        clear(T->Right);

        delete T;
        T = NIL;
    }

public:

    Node *Root;
    Node *NIL; ///dummy node

    IndexableTreap() : Root(nullptr), NIL(nullptr)
    {
        srand(time(nullptr));

        NIL = new Node(0, 0, 0, 0, nullptr, nullptr);
        Root = NIL;
    }

    ~IndexableTreap()
    {
        this->clear();
    }

    IndexableTreap(IndexableTreap &IT) : Root(nullptr), NIL(nullptr)
    {
        srand(time(nullptr));

        NIL = new Node(0, 0, 0, 0, nullptr, nullptr);
        Root = NIL;

        for (size_t i = 1; i <= IT.size(); ++i)
        {
            int key = IT.kth_element(i);
            this->insert_after(i - 1, key);
        }
    }

    IndexableTreap& operator = (IndexableTreap &IT)
    {
        Root = nullptr;
        NIL = nullptr;

        srand(time(nullptr));

        NIL = new Node(0, 0, 0, 0, nullptr, nullptr);
        Root = NIL;

        for (size_t i = 1; i <= IT.size(); ++i)
        {
            int key = IT.kth_element(i);
            this->insert_after(i - 1, key);
        }

        return *this;
    }

    ///Modifiers ----------------------------------------------------------------------
    void insert_after(const size_t position, const int key) ///inserts after position
    {
        assert(position <= this->size());

        insert_after(Root, position, key, rand() % (MAX_PRIORITY - 2) + 1);
    }

    void erase(const size_t position)
    {
        assert(1 <= position);
        assert(position <= this->size());

        erase(Root, position);
    }

    void change_key(const size_t position, const int key)
    {
        assert(1 <= position);
        assert(position <= this->size());

        change_key(Root, position, key);
    }

    void clear()
    {
        clear(Root);
    }
    ///---------------------------------------------------------------------------------

    void reverse(const size_t start, const size_t finish)
    {
        assert(1 <= start);
        assert(start <= finish);
        assert(finish <= this->size());

        Node *tmp, *T1, *T2, *T3;

        split(this->Root, tmp, T3, finish); ///tmp = [1...finish] | T3 = [finish+1...treap.size()]
        split(tmp, T1, T2, start - 1);      ///T1 = [1...start-1] | T2 = [start...finish]

        T2->Reverse = true;

        join(tmp, T1, T2);
        join(this->Root, tmp, T3);
    }

    size_t query(const size_t start, const size_t finish)
    {
        assert(1 <= start);
        assert(start <= finish);
        assert(finish <= this->size());

        Node *tmp, *T1, *T2, *T3;

        split(this->Root, tmp, T3, finish);
        split(tmp, T1, T2, start - 1);

        size_t sum = T2->Sum;

        join(tmp, T1, T2);
        join(this->Root, tmp, T3);

        return sum;
    }

    ///Element access --------------------------------------------------------------------------
    int kth_element(const size_t position)
    {
        assert(1 <= position);
        assert(position <= this->size());

        return kth_element(Root, position);
    }

    int at(const size_t position)
    {
        return kth_element(position);
    }

    int operator [] (const size_t position)
    {
        return kth_element(position);
    }

    int front()
    {
        assert(this->empty() == false);

        return kth_element(1);
    }

    int back()
    {
        assert(this->empty() == false);

        return kth_element(this->size());
    }
    ///---------------------------------------------------------------------------------

    void inorder(vector<int> &keys)
    {
        inorder(Root, keys);
    }

    ///Capacity ------------------------------------------------------------------------
    size_t size() const
    {
        return Root->Size;
    }

    bool empty() const
    {
        return (Root->Size == 0);
    }
    ///---------------------------------------------------------------------------------
};

IndexableTreap T;

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

    int N, rev, k, x, y;
    char oper;
    f >> N >> rev;

    for (int i = 1; i <= N; ++i)
    {
        f >> oper;

        switch (oper)
        {
            case 'A':
            {
                f >> k;
                g << T.kth_element(k) << "\n";
                break;
            }
            case 'D':
            {
                f >> x >> y;
                for ( int j = x; j <= y; ++j ) T.erase(x);
                break;
            }
            case 'I':
            {
                f >> x >> y;
                T.insert_after(x - 1, y);
                break;
            }
            case 'R':
            {
                f >> x >> y;
                T.reverse( x, y );
                break;
            }
        }
    }

    vector<int> v;
    T.inorder(v);

    for (auto it: v)
        g << it << " ";

    return 0;
}