主席树太费空间了,而本题也无需维护任何区间信息,只是查询历史版本点值,没必要构造可持久化线段树,我们可以构建结构类似于 BST 的可持久化数据结构,这样每个非叶节点也会带有权值,不会被浪费掉
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;
}