109 lines
2.2 KiB
C++
109 lines
2.2 KiB
C++
#include <string>
|
|
#include <cstdlib>
|
|
#include <utility>
|
|
|
|
using std::string;
|
|
typedef unsigned long long count_type;
|
|
#define RAND_MAX (1 << 62)
|
|
class line;
|
|
typedef std::pair<line*, line*> two_lines;
|
|
|
|
// 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) {}
|
|
};
|
|
|
|
// Treap representation of a file
|
|
class file {
|
|
line* root;
|
|
|
|
// Get size uf a subtreap
|
|
int 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->size -= two.first->size;
|
|
return {two.first, l};
|
|
}
|
|
else {
|
|
// In the right subtree
|
|
auto two = split(l->right, k - (1+get_size(l->left)));
|
|
l->size -= two.second->size;
|
|
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 += b->size;
|
|
a->right = join(a->right, b);
|
|
return a;
|
|
}
|
|
else {
|
|
b->size += a->size;
|
|
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 > l->size+1)
|
|
return find(l->right, k - (1+get_size(l->left)) );
|
|
else
|
|
return l;
|
|
}
|
|
|
|
public:
|
|
file() {
|
|
srand(120);
|
|
root = nullptr;
|
|
}
|
|
// Don't find index k, but k-th line -> +1
|
|
line* find(count_type k) {
|
|
if(k >= root->size)
|
|
return nullptr;
|
|
return find(root, k+1);
|
|
}
|
|
|
|
// File access
|
|
void insert(int k, string s) {
|
|
line *l = new line(rand(), s);
|
|
|
|
if(root == nullptr) {
|
|
root = l;
|
|
return;
|
|
}
|
|
|
|
auto two = split(root, k);
|
|
join(two.first, l);
|
|
join(two);
|
|
}
|
|
// Line removal
|
|
void remove(count_type k) {
|
|
auto two = split(root, k);
|
|
two.first = split(two.first, k-1).first;
|
|
join(two);
|
|
}
|
|
};
|