#include #include #include #include using std::string; typedef unsigned long long count_type; // Treap node representation of a line struct line { count_type priority, size; string text; line *left, *right; line(count_type _p, string _t) : priority(_p), text(_t), size(1), left(nullptr), right(nullptr) {} }; typedef std::pair two_lines; // Treap representation of a file class treap { line* root; // Get size uf a subtreap count_type get_size(line* l) { if(l == nullptr) return 0; return l->size; } // Split treap by k-th element // Hopefully with sizes two_lines split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; if(get_size(l->left) >= k) { // In the left subtree auto two = split(l->left, k); l->left = two.second; l->size -= get_size(two.first); return {two.first, l}; } else { // In the right subtree auto two = split(l->right, k - (1+get_size(l->left))); l->right = two.first; l->size -= get_size(two.second); return {l, two.second}; } } // Join two treaps // Hopefully with working sizes line* join(line *a, line *b) { if(a == nullptr) return b; if(b == nullptr) return a; if(a->priority < b->priority) { a->size += get_size(b); a->right = join(a->right, b); return a; } else { b->size += get_size(a); b->left = join(a, b->left); return b; } } line* join(two_lines two) { return join(two.first, two.second); } // Find k-th line of file line* find(line* l, count_type k) { if(l == nullptr) return nullptr; if(k <= get_size(l->left)) return find(l->left, k); else if(k == get_size(l->left)+1) return l; else return find(l->right, k - (1+get_size(l->left)) ); } public: treap() { srand(120); root = nullptr; } // File access line* find(count_type k) { if(k >= root->size) return nullptr; // Don't find index k, but k-th line -> +1 return find(root, k+1); } void clear() { while(size() > 0) { auto two = split(root, 1); root = two.second; delete two.first; } } // Line insert void insert(count_type k, string s) { line *l = new line(rand(), s); if(root == nullptr) { root = l; return; } auto two = split(root, k); two.first = join(two.first, l); root = join(two); } void append(string s) { insert(size(), s); } // Line removal void remove(count_type k) { auto two = split(root, k+1); auto first_split = split(two.first, k); delete first_split.second; two.first = first_split.first; root = join(two); } void pop() { remove(size()); } count_type size() { return get_size(root); } };