#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 1e8;
struct TreeNode{
int val;
TreeNode *left,*right;
TreeNode(int _val):val(_val),left(NULL),right(NULL){}
}*root;
void insert(TreeNode* &root,int x){
if(!root) root = new TreeNode(x);
else if(x < root->val) insert(root->left,x);
else insert(root->right,x);
}
void remove(TreeNode* &root,int x){
if(!root) return;
if(x < root->val) remove(root->left,x);
else if(x > root->val) remove(root->right,x);
else{
if(!root->left && !root->right) root = NULL; //删除节点是叶子节点,直接删除
else if(!root->left) root = root->right; //删除节点若只有左子树或者右子树,让其替代删除节点
else if(!root->right) root = root->left;
else{ //删除节点左右子树都有,做到其删除节点左子树的最右的节点,将值赋值给删除节点
auto p = root->left; //然后删除最右的节点
while(p->right) p = p->right;
root->val = p->val;
remove(root->left,p->val);
}
}
}
//输出数值x的前驱(前驱定义为现有所有数中小于 x的最大的数)
int get_pre(TreeNode* root,int x){
if(!root) return -INF;
if(root->val >= x) return get_pre(root->left,x);
return max(root->val,get_pre(root->right,x));
}
//输出数值x的后继(后继定义为现有所有数中大于 x的最小的数)
int get_suc(TreeNode* root,int x){
if(!root) return INF;
if(root->val <= x) return get_suc(root->right,x);
return min(root->val,get_suc(root->left,x));
}
int main(){
int n;
cin >> n;
while(n--){
int t,x;
cin >> t >> x;
if(t==1) insert(root,x);
else if(t==2) remove(root,x);
else if(t==3) cout<<get_pre(root,x) << endl;
else cout << get_suc(root,x) <<endl;
}
return 0;
}