/*
#include<iostream>
#include<random>
using namespace std;
const int INF=2147483647;
mt19937 Rand(time(nullptr));
struct node{
node *l,*r;
int val,siz,pri;
node(int _val): l(nullptr),r(nullptr),val(_val),siz(1),pri(Rand()){}
node(const node *u): l(u->l),r(u->r),val(u->val),siz(u->siz),pri(u->pri){}//克隆,即可持久化思想,将未改变的版本进行共用
void pushup(){
siz=1;
if(l)
siz+=l->siz;
if(r)
siz+=r->siz;
}
};
struct FHQ_treap{
private:
pair<node *,node *> split(node *u,int val){
if(!u)
return {nullptr,nullptr};
auto newnode=new node(u);
if(newnode->val<=val){
auto tmp=split(newnode->r,val);
newnode->r=tmp.first;
newnode->pushup();
return {newnode,tmp.second};
}
else{
auto tmp=split(newnode->l,val);
newnode->l=tmp.second;
newnode->pushup();
return {tmp.first,newnode};
}
}
pair<node *,node *> splitori(node *u,int val){
if(u==nullptr)
return {nullptr,nullptr};
if(u->val<=val){
auto tmp=splitori(u->r,val);
u->r=tmp.first;
u->pushup();
return {u,tmp.second};
}
else{
auto tmp=splitori(u->l,val);
u->l=tmp.second;
u->pushup();
return {tmp.first,u};
}
}
node *merge(node *u,node *v){
if(!u)
return v? new node(v):nullptr;
if(!v)
return u? new node(u):nullptr;
if(u->pri<v->pri){
auto newnode=new node(u);
newnode->r=merge(newnode->r,v->l);
newnode->pushup();
return newnode;
}
else{
auto newnode=new node(v);
newnode->l=merge(u,newnode->l);
newnode->pushup();
return newnode;
}
}
node *mergeori(node *u,node *v){
if(u==nullptr)
return v;
if(v==nullptr)
return u;
if(u->pri<v->pri){
u->r=mergeori(u->r,v);
u->pushup();
return u;
}
else{
v->l=mergeori(u,v->l);
v->pushup();
return v;
}
}
node *insert(node *u,int val){
auto tmp=split(u,val-1);
auto newnode=new node(val);
return merge(merge(tmp.first,newnode),tmp.second);
}
node *erase(node *u,int val){
auto tmp=split(u,val-1);
auto rtr=split(tmp.second,val);
if(rtr.first){
// 如果存在值为val的节点,删除它
// 注意:这里不直接删除,因为可能有其他版本引用
auto merged=merge(rtr.first->l,rtr.first->r);
return merged;
}
return merge(tmp.first,merge(rtr.first,rtr.second));
}
int queryval(node *u,int val){
auto tmp=splitori(u,val-1);
int res=tmp.first==nullptr? 0+1:tmp.first->siz+1;
return res;
}
int queryrank(node *u,int rnk){
auto pos=u;
while(pos){
int lsiz=pos->l==nullptr? 0:pos->l->siz;
if(rnk==lsiz+1)
return pos->val;
if(rnk<lsiz+1)
pos=pos->l;
else{
rnk-=lsiz+1;
pos=pos->r;
}
}
return 0;
}
public:
vector<node *> versions;
void init(){
versions.push_back(nullptr);
// 版本0:空树
}
// 创建新版本
int insert(int version,int val){
node* newroot=insert(versions[version],val);
versions.push_back(newroot);
return versions.size()-1;
}
int erase(int version,int val){
node* newroot=erase(versions[version],val);
versions.push_back(newroot);
return versions.size()-1;
}
int queryval(int version,int val){
return queryval(versions[version],val);
}
int queryrank(int version, int k){
return queryrank(versions[version], k);
}
int getpre(int version,int val){
auto res=queryval(version,queryrank(version,val)-1);
if(!res)
return -INF;
return res;
}
int getnext(int version,int val){
auto res=queryval(version,queryrank(version,val+1));
if(!res)
return INF;
return res;
}
};
FHQ_treap tr;
int main(){
cin.tie(nullptr)->sync_with_stdio(false);
}
*/
#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline void read(int& a){
int s=0, w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if (ch=='-')
w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
a=s*w;
}
void write(int x){
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
const int N=3e7+5;
const int INF=2147483647;
int siz[N],ls[N],rs[N],val[N],pri[N],root[N];
int cnt,n;
void updata(int a,int b){
siz[a]=siz[b];
val[a]=val[b];
pri[a]=pri[b];
ls[a]=ls[b];
rs[a]=rs[b];
}
void up(int x){
if(x){
siz[x]=siz[ls[x]]+siz[rs[x]]+1;
}
}
void Split(int rt,int k,int &rt1,int &rt2){
if(!rt){
rt1=rt2=0;
return;
}
int new_rt=++cnt;
updata(new_rt,rt);
if(k<val[rt]){
rt2=new_rt;
Split(ls[rt],k,rt1,ls[rt2]);
up(rt2);
}
else{
rt1=new_rt;
Split(rs[rt],k,rs[rt1],rt2);
up(rt1);
}
}
int Merge(int rt1,int rt2){
if(!rt1 || !rt2) return rt1|rt2;
int new_rt=++cnt;
if(pri[rt1]<pri[rt2]){
updata(new_rt,rt1);
rs[new_rt]=Merge(rs[new_rt],rt2);
up(new_rt);
return new_rt;
}
else{
updata(new_rt,rt2);
ls[new_rt]=Merge(rt1,ls[new_rt]);
up(new_rt);
return new_rt;
}
}
int Rank(int rt,int v){
if(!rt) return 0;
if(v<val[rt]) return Rank(ls[rt],v);
else return siz[ls[rt]]+Rank(rs[rt],v)+1;
}
void insert(int &root,int v){
int new_rt=++cnt;
val[cnt]=v;
pri[cnt]=rand();
siz[cnt]=1;
ls[cnt]=rs[cnt]=0;
if(!root){
root=cnt;
return;
}
int rt1,rt2;
Split(root,v,rt1,rt2);
root=Merge(Merge(rt1,new_rt),rt2);
}
void erase(int &root,int v){
int rt1,rt2,rt3;
Split(root,v,rt1,rt3);
Split(rt1,v-1,rt1,rt2);
if(rt2){
int new_rt=Merge(ls[rt2],rs[rt2]);
root=Merge(rt1,Merge(new_rt,rt3));
}
else root=Merge(rt1,rt3);
}
int Kth(int rt, int k) {
if(k<=siz[ls[rt]]) return Kth(ls[rt],k);
else if(k==siz[ls[rt]]+1) return val[rt];
else return Kth(rs[rt],k-siz[ls[rt]]-1);
}
int pre(int rt,int x){
if(!rt) return -INF;
if(val[rt]<x) return max(val[rt],pre(rs[rt],x));
else return pre(ls[rt],x);
}
int nex(int rt,int x){
if(!rt) return INF;
if(val[rt]>x) return min(val[rt],nex(ls[rt],x));
else return nex(rs[rt],x);
}
signed main(){
read(n);
root[0]=0;
for(int i=1;i<=n;i++){
int v,opt,x;
read(v),read(opt),read(x);
root[i]=root[v];
if(opt==1) insert(root[i],x);
if(opt==2) erase(root[i],x);
if(opt==3) write(Rank(root[i],x-1)+1),printf("\n");
if(opt==4) write(Kth(root[i],x)),printf("\n");
if(opt==5) write(pre(root[i],x)),printf("\n");
if(opt==6) write(nex(root[i],x)),printf("\n");
}
return 0;
}