#include <bits/stdc++.h>
using i64 = long long;
struct Node {
int l = 0;
int r = 0;
i64 len = 0;
char ch = '\0';
};
constexpr int N = 1E7;
Node t[N];
int tot = 0;
void pull(int a) {
t[a].len = t[t[a].l].len + 1 + t[t[a].r].len;
}
std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
int copy(int a) {
int b = ++tot;
t[b] = t[a];
return b;
}
int build(const std::string &s, int l, int r) {
if (r - l == 0) {
return 0;
}
int x = (l + r) / 2;
int a = ++tot;
t[a].l = build(s, l, x);
t[a].r = build(s, x + 1, r);
t[a].ch = s[x];
pull(a);
return a;
}
int merge(int a, int b) {
if (a == 0) {
return b;
}
if (b == 0) {
return a;
}
if (rng() % (t[a].len + t[b].len) < t[a].len) {
int c = copy(a);
t[c].r = merge(t[a].r, b);
pull(c);
return c;
} else {
int c = copy(b);
t[c].l = merge(a, t[b].l);
pull(c);
return c;
}
}
std::pair<int, int> split(int a, i64 k) {
if (k == 0) {
return {0, a};
}
if (k == t[a].len) {
return {a, 0};
}
if (k <= t[t[a].l].len) {
auto [l, r] = split(t[a].l, k);
int c = copy(a);
t[c].l = r;
pull(c);
return {l, c};
} else {
auto [l, r] = split(t[a].r, k - 1 - t[t[a].l].len);
int c = copy(b);
t[c].r = l;
pull(c);
return {c, r};
}
}
void print(int a, i64 l, i64 r) {
if (l < t[t[a].l].len) {
print(t[a].l, l, std::min(r, t[t[a].l].len));
}
if (l <= t[t[a].l].len && r > t[t[a].l].len) {
std::cout << t[a].ch;
}
if (r > t[t[a].l].len + 1) {
print(t[a].r, std::max(0LL, l - 1 - t[t[a].l].len), r - 1 - t[t[a].l].len);
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::string line;
std::getline(std::cin, line);
std::vector<int> text{0};
int clip = 0;
std::vector<int> history{0};
int current = 0;
std::string input;
std::function<void(std::string, bool)> work = [&](std::string line, bool second) {
std::stringstream cmd(line);
input += line + '\n';
std::string op;
cmd >> op;
int a = text[history[current]];
if (op == "insert") {
i64 p;
std::string str;
cmd >> p >> str;
auto [L, R] = split(a, p);
history.resize(current + 1);
history.push_back(text.size());
text.push_back(merge(merge(L, build(str, 0, str.size())), R));
current += 1;
} else if (op == "erase") {
i64 l, r;
cmd >> l >> r;
auto [LM, R] = split(a, r);
auto [L, M] = split(LM, l);
history.resize(current + 1);
history.push_back(text.size());
text.push_back(merge(L, R));
current += 1;
} else if (op == "print") {
if (second) {
return;
}
i64 l, r;
cmd >> l >> r;
print(a, l, r);
std::cout << "\n";
} else if (op == "copy") {
i64 l, r;
cmd >> l >> r;
auto [LM, R] = split(a, r);
auto [L, M] = split(LM, l);
clip = M;
} else if (op == "cut") {
i64 l, r;
cmd >> l >> r;
auto [LM, R] = split(a, r);
auto [L, M] = split(LM, l);
clip = M;
history.resize(current + 1);
history.push_back(text.size());
text.push_back(merge(L, R));
current += 1;
} else if (op == "paste") {
i64 p;
cmd >> p;
auto [L, R] = split(a, p);
history.resize(current + 1);
history.push_back(text.size());
text.push_back(merge(merge(L, clip), R));
current += 1;
} else if (op == "serialize") {
if (second) {
return;
}
assert(input.size() <= 5000000);
for (auto c : input) {
int x = c / 16;
int y = c % 16;
std::cout << char(x < 10 ? '0' + x : 'A' + x - 10) << char(y < 10 ? '0' + y : 'A' + y - 10);
}
std::cout << "\n";
} else if (op == "deserialize") {
std::string str;
cmd >> str;
std::string t;
for (int i = 0; i < str.size(); i += 2) {
char x = str[i], y = str[i + 1];
int u = std::isdigit(x) ? x - '0' : x - 'A' + 10;
int v = std::isdigit(y) ? y - '0' : y - 'A' + 10;
t += u * 16 + v;
}
std::stringstream input(t);
while (std::getline(input, line)) {
work(line, true);
}
int a = history[current];
history = {0, a};
current = 1;
// clip = 0;
} else if (op == "undo") {
if (current > 0) {
current -= 1;
}
} else if (op == "redo") {
if (current + 1 < history.size()) {
current += 1;
}
} else {
assert(false);
}
};
for (int i = 1; i <= n; i++) {
std::getline(std::cin, line);
work(line, false);
}
assert(tot < N);
return 0;
}