/*
* 本模板支持以下操作:
* 1.在任意位置插入一个整数
* 2.插入一个块(Block),包含多个整数
* 3.删除一个整数
* 4.输出第i位上的整数
* 注意:所有Insert(pos,data),均是在pos之后插入。
* BlockList::N是sqrt(n)的结果,它决定了块状链表的效率
*/
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define MAXSIZE 1000
namespace BlockList{
int N;
class Block{
public:
int size;
Block* next;
int data[MAXSIZE+2];
inline Block(){
size=0;
}
inline int& select(int x){
return data[x];
}
void Insert(int pos,int x);
void Delete(int pos);
};
inline void Block::Insert(int pos,int x){
this->size++;
for (int i=size;i>pos+1;–i){
data[i]=data[i-1];
}
data[pos+1]=x;
}
inline void Block::Delete(int pos){
for (int i=pos;i<size;++i){
data[i]=data[i+1];
}
size–;
}
class List{
public:
Block* Head;
int size;
inline List(){
size=0;
}
void Insert(const int,const Block*);
void Insert(const int,const int );
void Delete(int pos);
inline int get(int pos);
};
inline int List::get(int pos){
int sum=0;
if (pos>size) return -1;
for (Block* p=Head;p;p=p->next){
if (sum+p->size>=pos){
return p->data[pos-sum];
}
}
}
inline void Div(Block *data,const int pos){
if (pos<=data->size) return ;
Block *p1=new Block,*p2=new Block;
p1->size=pos;
for (int i=1;i<=pos;++i){
p1->data[i]=data->data[i];
}
p2->size=data->size-pos;
for (int i=1;i<=p2->size;++i){
p2->data[i]=data->data[i+pos];
}
p1->next=p2;
p2->next=data;
delete data;
data=p1;
}
inline void Union(Block *a,Block * b){
Block* p=new Block;
p->size=a->size+b->size;
for (int i=1;i<=a->size;++i){
p->data[i]=a->data[i];
}
for (int i=1;i<=b->size;++i){
p->data[i+a->size]=b->data[i];
}
p->next=b->next;
delete a;
delete b;
a=p;
}
void List::Insert(const int pos,const Block* x)
{
int sum=0;
if (!Head)
{
Block* p=new Block;
memcpy(p,x,sizeof(p));
size=x->size;
Head=p;
return ;
}
if (pos<Head->size){
Div(Head,pos);
Block* next=Head->next;
Block* p=new Block;
memcpy(p,x,sizeof(p));
Head->next=p;
p->next=next;
if (Head->size+p->size<N) Union(Head,p);
else if (p->size+next->size<N) Union(p,next);
return;
}
sum+=Head->size;
Block* pre=Head;
for (Block *p=Head->next;p;p=p->next)
{
sum+=p->size;
if (sum==pos){
Block *tmp=new Block;
memcpy(tmp,x,sizeof(tmp));
pre->next=tmp;
tmp->next=p;
if (pre->size+tmp->size<N){
Union(pre,tmp);
}else if (tmp->size+p->size<N){
Union(tmp,p);
}
return ;
}
if (sum>pos){
Block *tmp=new Block;
memcpy(tmp,x,sizeof(tmp));
Block *obj=p;
Div(p,pos-(sum-p->size));
Block *next=obj->next;
obj->next=tmp;
tmp->next=next;
if (pre->size+tmp->size<N){
Union(obj,tmp);
}else if (tmp->size+p->size<N){
Union(tmp,next);
}
return ;
}
pre=p;
}
}
void List::Insert(const int pos,const int x)
{
int sum=0;
size++;
if (!Head)
{
Block* p=new Block;
p->size=1;
p->data[1]=x;
Head=p;
return ;
}
if (pos<=Head->size){
Head->Insert(pos,x);
return;
}
sum+=Head->size;
Block* pre=Head;
for (Block *p=Head->next;p;p=p->next)
{
sum+=p->size;
if (sum>=pos){
p->Insert(pos-(sum-p->size),x);
return ;
}
}
}
inline void List::Delete(int pos){
int sum=0;
if (pos>size )return;
size–;
for (Block *p=Head;p;p=p->next){
if (sum+p->size>=pos){
p->Delete(pos-sum);
return ;
}
}
}
}
BlockList::List d;
int main(){
BlockList::N=500;
int op,tmp1,tmp2;
while (~scanf("%d",&op)){
if (op==1){
scanf("%d%d",&tmp1,&tmp2);
d.Insert(tmp1,tmp2);
}
if (op==2){
scanf("%d",&tmp1);
d.Delete(tmp1);
}
if (op==3){
scanf("%d",&tmp1);
printf("%dn",d.get(tmp1));
}
}
}