# 洛谷P3919 【模板】可持久化数组（可持久化线段树/平衡树）

Code;

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1000000 + 3;
int n, m, root[maxn], ls[maxn * 51], rs[maxn * 51], cnt_node;
long long  A[maxn], val[maxn * 51];
struct Segment_Tree
{
void build(int l,int r,int &o){
if(l > r) return ;
o = ++cnt_node;
int mid = (l + r) >> 1;
val[o] = A[mid];
build(l, mid - 1, ls[o]);
build(mid + 1, r, rs[o]);
}
int update(int l, int r, int k, long long  delta,  int o)
{
int oo = ++cnt_node;
val[oo] = val[o];
ls[oo] = ls[o];
rs[oo] = rs[o];
int mid = (l + r) >> 1;
if(k == mid) { val[oo] = delta;  return oo;}
if(k <= mid - 1) ls[oo] = update(l, mid - 1, k, delta, ls[o]);
else rs[oo] = update(mid + 1, r, k, delta, rs[o]);
return oo;
}
long long  query(int l,int r,int pos,int o)
{
int mid = (l + r) >> 1;
if(mid == pos) return val[o];
else if(mid - 1 >= pos) return query(l, mid - 1, pos, ls[o]);
else return query(mid + 1, r, pos , rs[o]);
}
}T;
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i) scanf("%lld",&A[i]);
T.build(1, n, root[0]);
for(int i = 1;i <= m; ++i)
{
int pre, opt, pos, v;
scanf("%d%d%d",&pre, &opt, &pos);
switch(opt)
{
case 1:
{
scanf("%d",&v);
root[i] = T.update(1, n, pos, v, root[pre]);
break;
}
case 2:
{
root[i] = root[pre];
printf("%lld\n", T.query(1, n, pos, root[i]));
break;
}
}
}

return 0;
}