可持久化线段树
模板题
###题面
主席树的指针是要加上取地址符的,因为这个指针在 上一层递归 或 初状态 被赋予了别的意义,例如 i代表上一个点的左儿子,而在此层递归中,此点(即上一个点的左儿子)在数组中的位置是不同的,所以要转移回去
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define rg register using namespace std; int n,m,root[1000001],num; struct pp { int le,ri,ls,rs,it; }tr[25000001]; inline int read() { rg int save=0,w=1;char q; while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();} while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar(); return save*w; } void build(rg int l,rg int r,rg int &i) { //++num:开点 i=++num; tr[i].le=l,tr[i].ri=r; if(l==r) { tr[i].it=read(); return; } rg int mid=(l+r)>>1; build(l,mid,tr[i].ls); build(mid+1,r,tr[i].rs); } void modify(rg int &i,rg int k,rg int x) { tr[++num]=tr[i]; i=num; if(tr[i].le==tr[i].ri) { tr[i].it=x; return; } rg int mid=(tr[i].le+tr[i].ri)>>1; if(k<=mid)modify(tr[i].ls,k,x); else modify(tr[i].rs,k,x); } int ask(rg int i,rg int k) { if(tr[i].le==tr[i].ri)return tr[i].it; rg int mid=(tr[i].le+tr[i].ri)>>1; if(k<=mid)return ask(tr[i].ls,k); else return ask(tr[i].rs,k); } int main() { n=read(),m=read(); rg int i,j; build(1,n,root[0]); for(i=1;i<=m;++i) { rg int ver=read(),op=read(); if(op==1) { rg int k=read(),x=read(); root[i]=root[ver]; modify(root[i],k,x); } else { rg int k=read(); root[i]=root[ver]; printf("%d\n",ask(root[i],k)); } } return 0; }