#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<climits>
#include<cctype>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1000005;
int n,m;
struct PerSegmentTree
{
int a[maxn];
int val[maxn * 25], cnt; //sum记录原数组区间[1,k]的改编号对应区间值的数量
int ls[maxn * 25], rs[maxn * 25]; //ls左二子,rs右儿子
int root[maxn]; //第i棵线段树的根编号
PerSegmentTree()
{
cnt=0;
}
int build(int l, int r)
{
int now = ++cnt;
if (l == r)
{
val[now]=a[l];
return now;
}
int mid = (l + r) >> 1;
ls[now] = build(l, mid);
rs[now] = build(mid + 1, r);
return now;
}
//将位置y修改为k
int modify(int x,int l, int r, int y, int k)
{
int now = ++cnt;
if (l == r)
{
val[now] = k;
return now;
}
int mid = (l + r) >> 1;
if (y <= mid)
{
ls[now] = modify(ls[x],1,mid,y,k);
rs[now] = rs[x];
}
else
{
ls[now] = ls[x];
rs[now] = modify(rs[x],mid+1,r,y,k);
}
return now;
}
int query(int x,int l, int r, int y)//询问x版本y位置的值
{
if (l == r)
return val[x];
int mid = (l + r) >> 1;
if (y <= mid)
return query(ls[x],l, mid, y);
return query(rs[x],mid + 1, r, y);
}
} pst;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&pst.a[i]);
}
pst.root[0]=pst.build(1,n);
for(int i=1;i<=m;i++)
{
int ver,op,loc,v;
scanf("%d%d%d",&ver,&op,&loc);
if(op==1)
{
scanf("%d",&v);
pst.root[i]=pst.modify(pst.root[ver],1,n,loc,v);
}
else
{
printf("%d\n",pst.query(pst.root[ver],1,n,loc));
pst.root[i]=pst.root[ver];
}
}
}