/*
*
* 伸展树简单应用
*
*/
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
char buf[1024*1024*5];
#define MAX_SPLAY_NODE_NUM 2000000
struct Node {
int child[2]; // 左右子节点编号
int parent; // 父节点编号
int val; // 节点数值
int size; // 子树大小
void init(int p, int v) {
child[0] = child[1] = 0;
parent = p;
val = v;
size = 1;
}
} __splay_node_pool[MAX_SPLAY_NODE_NUM];
int __splay_pool_pos = 1;
class SplayTree {
private:
int __root; // 根节点编号
Node* __pool; // 对象池
int& __pool_pos; // 对象池最后一个分配位置
class __init_guard {
public:
__init_guard() {
__splay_node_pool[0].init(0, 0);
__splay_node_pool[0].size = 0;
}
};
static __init_guard __guard;
public:
SplayTree() : __pool_pos(__splay_pool_pos), __root(0), __pool(__splay_node_pool) {
}
// 搬移函数,将编号为x的节点通过旋转搬移到k号节点的下面
void move(int x, int k) {
__move(x, k);
}
// 插入数值是val的节点
void insert(int val) {
int u = __root, p = 0;
while (u != 0) {
p = u;
u = __pool[u].child[val > __pool[u].val];
}
u = __pool_pos++;
if (p != 0) {
__pool[p].child[val > __pool[p].val] = u;
}
__pool[u].init(p, val);
while (p) {
__push_up(p);
p = __pool[p].parent;
}
__move(u, 0);
}
// 获取排名k的节点编号,返回0表示无解
int get_kth_idx(int k) {
int u = __root;
while (u) {
__push_down(u);
if (__pool[__pool[u].child[0]].size >= k) {
u = __pool[u].child[0];
} else if (__pool[__pool[u].child[0]].size + 1 == k) {
return u;
} else {
k -= __pool[__pool[u].child[0]].size + 1;
u = __pool[u].child[1];
}
}
return 0;
}
// 返回第一个数值大于等于val的节点编号, 返回0无解
int lower_bound(int node, int val) {
if (node == 0) {
return 0;
}
if (val <= __pool[node].val) {
int idx = lower_bound(__pool[node].child[0], val);
if (idx != 0) {
return idx;
}
return node;
} else {
return lower_bound(__pool[node].child[1], val);
}
}
// 删除子树
void del_sub_tree(int node) {
Node& parent_node = __pool[__pool[node].parent];
int p = __pool[node].parent;
if (parent_node.child[0] == node) {
parent_node.child[0] = 0;
} else {
parent_node.child[1] = 0;
}
while (p) {
__push_up(p);
p = __pool[p].parent;
}
}
// 第k个节点后面插入序列
void insert_kth_list(char* data, int len, int k) {
int idx1 = get_kth_idx(k);
int idx2 = get_kth_idx(k+1);
int idx3 = __build(data, 0, len-1, 0);
__move(idx1, 0);
__move(idx2, idx1);
__pool[idx2].child[0] = idx3;
__pool[idx3].parent = idx2;
__push_up(idx2);
__push_up(idx1);
}
// 删除第k1个位置到第k2个位置数据
void delete_range(int k1, int k2) {
int idx1 = get_kth_idx(k1-1);
int idx2 = get_kth_idx(k2+1);
__move(idx1, 0);
__move(idx2, idx1);
del_sub_tree(__pool[idx2].child[0]);
}
// 打印第k1个位置到第k2个位置的数据
void print_range(int k1, int k2) {
int idx1 = get_kth_idx(k1-1);
int idx2 = get_kth_idx(k2+1);
__move(idx1, 0);
__move(idx2, idx1);
int pos = 0;
__get_mid_travel_list(__pool[idx2].child[0], pos, buf);
buf[pos] = '\0';
printf("%s\n", buf);
}
// 获取树大小
int get_tree_size() {
return __pool[__root].size;
}
private:
// 信息上传函数(即根据子节点信息更新序号是idx的节点的信息)
void __push_up(int idx) {
Node& node = __pool[idx];
node.size = 1 + __pool[node.child[0]].size + __pool[node.child[1]].size;
}
// 懒标记下移操作
void __push_down(int idx) {
}
// 统一的左旋和右旋函数,将编号为x对应的节点网上一层旋转
void __rotate(int x) {
int y = __pool[x].parent, z = __pool[y].parent;
int k1 = __pool[y].child[1] == x, k2 = __pool[z].child[1] == y;
__pool[z].child[k2] = x;
__pool[x].parent = z;
__pool[y].child[k1] = __pool[x].child[k1^1];
__pool[__pool[x].child[k1^1]].parent = y;
__pool[x].child[k1^1] = y;
__pool[y].parent = x;
__push_up(y);
__push_up(x);
}
// 搬移函数,将编号为x的节点通过旋转搬移到k号节点的下面
// k = 0 表示将x节点搬移到根节点位置
void __move(int x, int k) {
while (__pool[x].parent != k) {
int y = __pool[x].parent, z = __pool[y].parent;
if (z != k) {
if ( (__pool[y].child[1] == x) != (__pool[z].child[1] == y) ) {
__rotate(x);
} else {
__rotate(y);
}
}
__rotate(x);
}
if (k == 0) {
__root = x;
}
}
void __get_mid_travel_list(int cur, int& pos, char* ans) {
if (cur == 0) {
return;
}
__push_down(cur);
__get_mid_travel_list(__pool[cur].child[0], pos, ans);
ans[pos++] = char(__pool[cur].val);
__get_mid_travel_list(__pool[cur].child[1], pos, ans);
}
// 序列构建子树
int __build(char* data, int start, int end, int parent) {
if (start > end) {
return 0;
}
if (start == end) {
int idx = __pool_pos++;
__pool[idx].init(parent, data[start]);
return idx;
}
int mid = (start + end) >> 1;
int idx = __pool_pos++;
__pool[idx].init(parent, data[mid]);
__pool[idx].child[0] = __build(data, start, mid-1, idx);
__pool[idx].child[1] = __build(data, mid+1, end, idx);
__push_up(idx);
return idx;
}
};
SplayTree::__init_guard SplayTree::__guard;
char s[1024*1024*5];
int main() {
//freopen("/Users/grh/Programming/CLionProjects/Test/data.txt", "r", stdin);
int cmd_n, pos, n;
int cur_pos = 1, read_cnt = 0, len = 0;
SplayTree tree;
tree.insert('#');
tree.insert('#');
scanf("%d", &cmd_n);
while (cmd_n--) {
scanf("%s", s);
if (strcmp(s, "Move") == 0) {
scanf("%d", &pos);
cur_pos = pos+1;
cur_pos = min(tree.get_tree_size() - 1, cur_pos);
} else if (strcmp(s, "Insert") == 0) {
scanf("%d", &n);
read_cnt = 0;
char ch;
while (read_cnt < n) {
ch = getchar();
if (!(ch >= 32 and ch <= 126)) {
continue;
}
s[read_cnt++] = ch;
}
tree.insert_kth_list(s, n, cur_pos);
} else if (strcmp(s, "Delete") == 0) {
scanf("%d", &n);
int total_len = tree.get_tree_size();
int start = cur_pos + 1;
int end = min(total_len - 1, start + n - 1);
tree.delete_range(start, end);
} else if (strcmp(s, "Get") == 0) {
scanf("%d", &n);
int total_len = tree.get_tree_size();
int start = cur_pos + 1;
int end = min(total_len - 1, start + n - 1);
tree.print_range(start, end);
} else if (strcmp(s, "Prev") == 0) {
cur_pos -= 1;
cur_pos = max(1, cur_pos);
} else if (strcmp(s, "Next") == 0) {
cur_pos += 1;
cur_pos = min(tree.get_tree_size() - 1, cur_pos);
}
}
return 0;
}