Cod sursa(job #1479470)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 31 august 2015 14:14:49
Problema Secv8 Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 7.7 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 Max;

        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), Max(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)
    {
        if (T != NIL)
        {
            T->Size = 1 + T->Left->Size + T->Right->Size;
            T->Max = max(T->Key, max(T->Left->Max, T->Right->Max));
        }
    }

    Node* rotate_to_right(Node* &T)
    {
        Node *tmp = T->Left;
        T->Left = tmp->Right;
        tmp->Right = T;

        update(T);
        update(tmp);

        return tmp;
    }

    Node* rotate_to_left(Node* &T)
    {
        Node *tmp = T->Right;
        T->Right = tmp->Left;
        tmp->Left = T;

        update(T);
        update(tmp);

        return tmp;
    }

    void balance(Node* &T)
    {
        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(Node* &T, size_t position, int key, 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(T->Left, position, key, priority);
            else
                insert(T->Right, position - 1 - T->Left->Size, key, priority);

            balance(T);
        }
    }

    void change_key(Node* &T, const int key, size_t position)
    {
        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, key, position);
            else
                change_key(T->Right, key, position - 1 - T->Left->Size);
        }

        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)
    {
        insert(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);
    }

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;
    }

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

        insert(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 int key, const size_t position)
    {
        assert(1 <= position);
        assert(position <= this->size());

        change_key(Root, key, position);
    }

    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);
        split(tmp, T1, T2, start - 1);

        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 maxim = T2->Max;

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

        return maxim;
    }

    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);
    }

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

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

int N, M, a, b, c;

int main()
{
    freopen("secv8.in", "r", stdin);
    freopen("secv8.out", "w", stdout);

    IndexableTreap T;

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

    cin >> N >> rev;

    while ( N-- )
    {
        cin >> oper;

        switch ( oper )
        {
            case 'A':
            {
                cin >> k;
                printf("%d\n", T.kth_element(k));
                break;
            }
            case 'D':
            {
                cin >> x >> y;

                for (int i = x; i <= y; ++i)
                    T.erase(x);

                break;
            }
            case 'I':
            {
                cin >> x >> y;

                if (x > 1)
                    x--;

                T.insert(y, x);
                break;
            }
            case 'R':
            {
                cin >> x >> y;
                T.reverse(x, y);
                break;
            }
        }

    }

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

    for (int x: v)
        cout << x << " ";

    return 0;
}