#include<bits/stdc++.h>
#define endl '\n';
using namespace std;
const int N = 3e5 + 5;
struct Node{
int ls, rs;
int val, key;
int size;
}tree[N], tree2[N];
int tot2, root2;
inline int newnode2(int val){
tot2++;
tree2[tot2].val = val;
tree2[tot2].ls = 0;
tree2[tot2].rs = 0;
tree2[tot2].key = rand();
tree2[tot2].size = 1;
return tot2;
}
inline void update2(int node){
tree2[node].size = tree2[tree2[node].ls].size + tree2[tree2[node].rs].size + 1;
}
void split2(int node, int val, int &r1, int &r2){
if(!node){
r1 = 0;
r2 = 0;
return ;
}
if(tree2[node].val <= val){
r1 = node;
split2(tree2[node].rs, val, tree2[node].rs, r2);
}
else{
r2 = node;
split2(tree2[node].ls, val, r1, tree2[node].ls);
}
update2(node);
}
int merge2(int x, int y){
if(!x || !y){
return x + y;
}
if(tree2[x].key > tree2[y].key){
tree2[x].rs = merge2(tree2[x].rs, y);
update2(x);
return x;
}
else{
tree2[y].ls = merge2(x, tree2[y].ls);
update2(y);
return y;
}
}
int tot, root;
inline int newnode(int val){
tot++;
tree[tot].val = val;
tree[tot].ls = 0;
tree[tot].rs = 0;
tree[tot].key = rand();
tree[tot].size = 1;
return tot;
}
inline void update(int node){
tree[node].size = tree[tree[node].ls].size + tree[tree[node].rs].size + 1;
}
void split(int node, int val, int &r1, int &r2){
if(!node){
r1 = 0;
r2 = 0;
return ;
}
if(tree[node].val <= val){
r1 = node;
split(tree[node].rs, val, tree[node].rs, r2);
}
else{
r2 = node;
split(tree[node].ls, val, r1, tree[node].ls);
}
update(node);
}
int merge(int x, int y){
if(!x || !y){
return x + y;
}
if(tree[x].key > tree[y].key){
tree[x].rs = merge(tree[x].rs, y);
update(x);
return x;
}
else{
tree[y].ls = merge(x, tree[y].ls);
update(y);
return y;
}
}
int ans1, ans2;
void dfs(int x){
if(!x){
return ;
}
ans1 += tree[x].val;
ans2 += tree2[x].val;
dfs(tree[x].ls);
dfs(tree[x].rs);
}
signed main(){
srand(time(0));
int op;
while(cin >> op){
if(op == -1){
break;
}
if(op == 1){
int w, c;
cin >> w >> c;
int x, y, z;
split2(root2, c, x, z);
split2(x, c - 1, x, y);
if(tree[y].size){
root2 = merge2(x, merge2(y, z));
}
else{
root = merge(x, merge(newnode(w), z));
root2 = merge2(x, merge2(newnode2(c), z));
}
}
else if(op == 2){
int x;
split(root, tree[root].size - 1, root, x);
split2(root2, tree2[root].size - 1, root2, x);
}
else{
int x;
split(root, 1, x, root);
split2(root2, 1, x, root2);
}
}
dfs(root);
cout << ans1 << " " << ans2;
return 0;
}