主席树太费空间了,而本题也无需维护任何区间信息,只是查询历史版本点值,没必要构造可持久化线段树,我们可以构建结构类似于 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 ", T.query(1, n, pos, root[i])); break; } } } return 0; }