Cod sursa(job #1755784)

Utilizator Al3ks1002Alex Cociorva Al3ks1002 Data 11 septembrie 2016 01:06:11
Problema Secv8 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.67 kb
#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;

// Class that represents an implicit treap.
template<class T>
class ImplicitTreap {
    public:
        /**
         * Default constructor for ImplicitTreap.
         */
        ImplicitTreap() {
            srand(time(0));
            root_ = nullptr;
        }

        /**
         * Finds the value from a given index.
         */
        T GetValueFromIndex(T index) {
            return FindValueFromIndex(root_, index);
        }

        /**
         *
         *
         */
        void InsertValueAtIndex(int index, T value) {
            pair<Node*, Node*> roots = Split(root_, index - 1);
            root_ = Merge(Merge(roots.first, new Node(value)), roots.second);
        }

        /**
         *
         *
         */
        void DeleteInterval(int left_index, int right_index) {
            pair<Node*, Node*> left_interval = Split(root_, left_index - 1);
            pair<Node*, Node*> middle_interval =
                Split(left_interval.second, right_index - left_index + 1);
            DeleteTreap(middle_interval.first);
            root_ = Merge(left_interval.first, middle_interval.second);
        }

        /**
         *
         */
        void ReverseInterval(int left_index, int right_index) {
            pair<Node*, Node*> left_interval = Split(root_, left_index - 1);
            pair<Node*, Node*> middle_interval =
                Split(left_interval.second, right_index - left_index + 1);
            Reverse(middle_interval.first);
            root_ = Merge(Merge(left_interval.first, middle_interval.first),
                          middle_interval.second);
        }

        /**
         * Returns the size of the treap.
         */
        int Size() const {
            return GetSubtreeSize(root_);
        }

        /**
         *
         */
        void Print()  {
            PrintTreap(root_);
        }

    private:
        struct Node {
            const T value_;
            const int priority_;
            Node* left_;
            Node* right_;
            int subtree_;
            bool is_reversed_;

            Node(int value) : value_(value), left_(nullptr), right_(nullptr),
                priority_((rand() << 16) ^ rand()), subtree_(1), is_reversed_(false) {}
        };

        int GetSubtreeSize(Node* node) const {
            return node == nullptr ? 0 : node->subtree_;
        }

        void UpdateNode(Node* node) {
            if (node == nullptr) {
                return;
            }
            node->subtree_ = 1 + GetSubtreeSize(node->left_)
                             + GetSubtreeSize(node->right_);
        }

        pair<Node*, Node*> Split(Node* node, int index) {
            if (node == nullptr) {
                return {nullptr, nullptr};
            }

            Propagate(node);

            pair<Node*, Node*> roots;
            int current_index = GetSubtreeSize(node->left_) + 1;
            if (current_index <= index) {
                roots = Split(node->right_, index - current_index);
                node->right_ = roots.first;
                roots.first = node;
            } else {
                roots = Split(node->left_, index);
                node->left_ = roots.second;
                roots.second = node;
            }

            UpdateNode(node);
            return roots;
        }

        Node* Merge(Node* left_root, Node* right_root) {
            Propagate(left_root);
            Propagate(right_root);

            if (left_root == nullptr) {
                return right_root;
            }

            if (right_root == nullptr) {
                return left_root;
            }

            if (left_root->priority_ > right_root->priority_) {
                left_root->right_ = Merge(left_root->right_, right_root);
                UpdateNode(left_root);
                return left_root;
            } else {
                right_root->left_ = Merge(left_root, right_root->left_);
                UpdateNode(right_root);
                return right_root;
            }
        }

        T FindValueFromIndex(Node* node, int index) {
            Propagate(node);

            int current_index = GetSubtreeSize(node->left_) + 1;
            if (current_index == index) {
                return node->value_;
            }
            if (current_index < index) {
                return FindValueFromIndex(node->right_, index - current_index);
            } else {
                return FindValueFromIndex(node->left_, index);
            }
        }

        void Propagate(Node* node) {
            if (node == nullptr || node->is_reversed_ == false) {
                return;
            }
            node->is_reversed_ = false;
            Reverse(node->left_);
            Reverse(node->right_);
            swap(node->left_, node->right_);
        }

        void Reverse(Node* node) {
            if (node == nullptr) {
                return;
            }
            node->is_reversed_ ^= 1;
        }

        void DeleteTreap(Node* node) {
            if (node == nullptr) {
                return;
            }
            if (node->left_ != nullptr) {
                DeleteTreap(node->left_);
            }
            if (node->right_ != nullptr) {
                DeleteTreap(node->right_);
            }
            delete node;
        }

        void PrintTreap(Node* node) {
            if (node == nullptr) {
                return;
            }
            Propagate(node);
            if (node->left_ != nullptr) {
                PrintTreap(node->left_);
            }
            printf("%d ", node->value_);
            if (node->right_ != nullptr) {
                PrintTreap(node->right_);
            }
        }

        Node* root_;
};

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

    int t;
    int with_reverse;
    scanf("%d %d\n", &t, &with_reverse);
    assert(with_reverse <= 1);

    ImplicitTreap<int> treap;

    for (; t; t--) {
        char operation;
        scanf("%c ", &operation);

        switch (operation) {
        case 'I':
            int index;
            int value;
            scanf("%d %d\n", &index, &value);
            treap.InsertValueAtIndex(index, value);
            break;
        case 'A':
            scanf("%d\n", &index);
            printf("%d\n", treap.GetValueFromIndex(index));
            break;
        case 'R':
            int left_index;
            int right_index;
            scanf("%d %d\n", &left_index, &right_index);
            treap.ReverseInterval(left_index, right_index);
            break;
        default:
            scanf("%d %d\n", &left_index, &right_index);
            treap.DeleteInterval(left_index, right_index);
        }
    }

    treap.Print();

    return 0;
}