#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define MAX_NODE_NUM 100005
struct Node {
int child[2]; // 左右子节点编号
int parent; // 父节点编号
int val; // 节点数值
int size; // 子树大小
int flag; // 懒标记
} pool[MAX_NODE_NUM];
class SplayTree {
private:
int __root; // 根节点编号
int __pool_pos; // 对象池最后一个分配位置
public:
SplayTree(int node_num) {
__root = 0;
__pool_pos = 1;
memset(pool, 0, sizeof(Node) * (node_num+1));
}
// 翻转懒标记
void rev_flag(int idx) {
pool[idx].flag ^= 1;
}
int get_left_child(int idx) {
return pool[idx].child[0];
}
int get_right_child(int idx) {
return pool[idx].child[1];
}
int get_root() {
return __root;
}
// 搬移函数,将编号为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].parent = p;
pool[u].val = val;
__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;
}
void get_mid_travel_list(int* ans) {
int pos = 0;
__get_mid_travel_list(__root, pos, ans);
}
// 返回第一个数值大于等于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;
}
}
// 获取数值
int get_val(int idx) {
return pool[idx].val;
}
// 获取树大小
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;
}
/******* 此处 __flag_oper __push_down_child_flag 两个函数的逻辑需要根据不同的问题场景进行修改 **********/
// 懒标记对应的操作,默认什么操作也没有,具体使用时候在此处添加操作
void __flag_oper(int idx) {
}
// 修改子节点的标记函数,默认就是将标记下传,不同问题可能有不同处理方式,这里把逻辑提出来
void __push_down_child_flag(int idx) {
}
// 懒标记下移操作
void __push_down(int idx) {
if (pool[idx].flag) {
__flag_oper(idx);
__push_down_child_flag(idx);
pool[idx].flag = 0;
}
}
// 统一的左旋和右旋函数,将编号为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, int* ans) {
if (cur == 0) {
return;
}
__push_down(cur);
__get_mid_travel_list(pool[cur].child[0], pos, ans);
ans[pos++] = pool[cur].val;
__get_mid_travel_list(pool[cur].child[1], pos, ans);
}
};
int main(void) {
//freopen("/Users/grh/Programming/CLionProjects/Test/data.txt", "r", stdin);
int min_bound, cmd_num;
char s[2];
int val;
scanf("%d %d", &cmd_num, &min_bound);
SplayTree tree(MAX_NODE_NUM-3);
tree.insert(-0x7fffffff);
tree.insert(0x7fffffff);
int delta = 0;
int cnt = 0; // 加入过公司的员工数
for (int i = 0; i < cmd_num; i++) {
scanf("%s %d", s, &val);
if (s[0] == 'I') {
if (val >= min_bound) {
tree.insert(val - delta);
cnt += 1;
}
} else if (s[0] == 'A' || s[0] == 'S') {
delta += s[0] == 'A' ? val : -val;
int idx = tree.lower_bound(tree.get_root(), min_bound - delta);
if (idx != 0) {
// 把工资小于最小值的区段全部删掉
tree.move(idx, 0);
tree.move(1, idx);
tree.del_sub_tree(tree.get_right_child(1));
}
} else {
int idx = tree.get_kth_idx((tree.get_tree_size()-2 - val + 1)+1);
if (idx == 0 || tree.get_val(idx) == 0x7fffffff || tree.get_val(idx) == -0x7fffffff) {
printf("-1\n");
} else {
printf("%d\n", tree.get_val(idx)+delta, tree.get_val(idx));
}
}
}
printf("%d\n", cnt - (tree.get_tree_size()-2));
return 0;
}