可持久化数组学习笔记
推荐先阅读:可持久化线段树学习笔记
一、定义:
可进行修改,并支持如下两功能的数组:
1.在某个历史版本上修改某一个位置上的值
2.访问某个历史版本上的某一位置的值
二、原理:
如果你已经学会了可持久化线段树(我就当你会了,不会见题头),会发现其实可持久化数组已经*含在**树中,或者说借**树实现的
建树与修改操作与**树完全相同:通过共享节点最小化空间
查询时直接在目标版本中查询即可
完整代码:
#include<cstdio> #include<algorithm> #define maxn 200010 #define mid (l+r)/2 using namespace std; struct node { int val,l,r; }tree[20000010]; int root[maxn<<5]; int a[maxn<<5],n,m,cc; int cnt; void build(int l,int r,int &rt) { rt=++cnt; if(l==r) { tree[rt].val=a[l]; return; } build(l,mid,tree[rt].l); build(mid+1,r,tree[rt].r); } void update(int num,int &rt,int l,int r) { tree[++cnt]=tree[rt]; rt=cnt; if(l==r) { tree[rt].val=cc; return; } if(num<=mid) update(num,tree[rt].l,l,mid); else update(num,tree[rt].r,mid+1,r); } int query(int rt,int l,int r,int num) { if(l==r) return tree[rt].val; if(num<=mid) return query(tree[rt].l,l,mid,num); else return query(tree[rt].r,mid+1,r,num); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,root[0]); for(int i=1;i<=m;i++) { int ty,id,bb; scanf("%d%d%d",&id,&ty,&bb); if(ty==1) { scanf("%d",&cc); root[i]=root[id]; update(bb,root[i],1,n); } if(ty==2) { printf("%d\n",query(root[id],1,n,bb)); root[i]=root[id]; } } return 0; }