// 大视野 1503 郁闷的出纳员 Splay 初步
//
// 解题思路:
//
// 参照大牛的思路,将增删所有的部分用一个变量w表示
// 对于工资的加减就是对w的操作.插入的时候只要先减
// 去这个影响就ok了.然后就是裸的Splay啦,注意第k多
// 的意思是从大到小...好吧这里我傻逼了
//
// 感悟:
//
// 这道题坑爹的是就在于,我理解了思路,参照大神的模板
// 自己硬敲了一发,结果wa了十几发,找茬也找不出来什么
// 然后,自己将版主的代码一交,好家伙,跟我一样,顿时内
// 心,拔凉拔凉的,然后一直在思考,还是没有什么思路,看
// 着,另外一位大牛的思路,跟之前的一模一样,一个wa一
// 个ac,我还是挺纳闷儿的,哎,菜鸟的痛啊,自己还是要好
// 好理解,继续加油吧~~~~FIGHTING!!!
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define rep(x,a,b,c) for(int x = a; x <= b; x += c)
using namespace std;
const int MAX_N = 311111;
const int INF = 2e9 + 9;
int N,M;
int w;
int ans;
struct SplayTree{
int ch[MAX_N][2];
int val[MAX_N];
int sum[MAX_N];
int pre[MAX_N];
int rt;
int Siz;
int cnt[MAX_N];
inline void Push_up(int x){
sum[x] = sum[ch[x][0]] + sum[ch[x][1]] + cnt[x];
}
inline void init(){
Siz = 0;
cnt[0] = 0;
NewNode(0,rt,-INF);
NewNode(rt,ch[rt][1],INF);
sum[rt] = 2;
}
inline void NewNode(int y,int &x,int v){
x = ++Siz;
pre[x] = y;
ch[x][0] = ch[x][1] = 0;
val[x] = v;
sum[x] = 1;
cnt[x] = 1;
}
void Rotate(int x,int d){
int y = pre[x];
ch[y][d^1] = ch[x][d];
pre[ch[x][d]] = y;
pre[x] = pre[y];
if (pre[y])
ch[pre[y]][ch[pre[y]][1] == y] = x;
ch[x][d] = y;
pre[y] = x;
Push_up(y);
}
void Splay(int x,int goal){
while(pre[x] != goal){
if (pre[pre[x]] == goal){
if (ch[pre[x]][0] == x)
Rotate(x,1);
else Rotate(x,0);
}else {
int y = pre[x], z = pre[y];
if (ch[z][0] == y){
if (ch[y][0] == x){
Rotate(y,1);
Rotate(x,1);
}else {
Rotate(x,0);
Rotate(x,1);
}
}else {
if (ch[y][1] == x){
Rotate(y,0);
Rotate(x,0);
}else {
Rotate(x,1);
Rotate(x,0);
}
}
}
}
Push_up(x);
if (goal == 0) rt = x;
}
// void Insert(int v){ // 这个不对,中间的更新没有保存下来
// int x = rt;
// while(ch[x][val[x] < v]){
// if (v == val[x]){
// cnt[x]++;
// sum[x]++;
// Splay(x,0);
// Push_up(x);
// return ;
// }
// x = ch[x][val[x] < v];
// }
// NewNode(x,ch[x][val[x] < v],v);
// Splay(x,0);
// Push_up(x);
// }
void Insert(int &x,int v,int f){
if (!x){
NewNode(f,x,v);
Splay(x,0);
return ;
}
if (v == val[x]){
cnt[x]++;
sum[x]++;
Splay(x,0);
return ;
}else if (v < val[x]){
Insert(ch[x][0],v,x);
}else {
Insert(ch[x][1],v,x);
}
Push_up(x);
}
int F_min(int v){
int x = rt;
int ans = INF;
while(x){
if (val[x] == v) return v;
if (val[x] > v) ans = min(ans,val[x]);
if (val[x] > v) x = ch[x][0];
else x = ch[x][1];
}
return ans;
}
int F_root(int v){
int x = rt;
while(x){
if (val[x] == v) return x;
if (val[x] < v) x = ch[x][1];
else x = ch[x][0];
}
return 0;
}
int DeleteSubTree(int a){
int x = F_root(a);
int res = 0;
if (x){
Splay(1,0); // 将负无穷转到根
Splay(x,1); // 将x转到负无穷的下面,则x的左孩子就是可以删除的子树
res = sum[ch[x][0]];
ch[x][0] = 0;
Splay(x,0);
}
return res;
}
int GetK(int x,int k){
if (k < sum[ch[x][0]] + 1){
return GetK(ch[x][0],k);
}else if (k > sum[ch[x][0]] + cnt[x]){
return GetK(ch[x][1],k-sum[ch[x][0]]-cnt[x]);
}else {
Splay(x,0);
return val[x];
}
}
}spt;
void input(){
char op[5];
int x;
w = 0;
ans = 0;
spt.init();
rep(i,1,N,1){
scanf("%s%d",op,&x);
if (op[0] == 'I'){
if (x >= M)
spt.Insert(x-w);
//spt.Insert(spt.rt,x-w,0);
}else if (op[0] == 'S'){
w-=x;
//spt.DeleteTree(spt.rt,0);
ans += spt.DeleteSubTree(spt.F_min(M-w));
}else if (op[0] == 'A'){
w+=x;
}else {
if (x+2>spt.sum[spt.rt]) puts("-1");
else printf("%d\n",spt.GetK(spt.rt,spt.sum[spt.rt]-x)+w);
}
}
printf("%d\n",ans);
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d",&N,&M);
input();
return 0;
}