P3919 【模板】可持久化线段树 1(可持久化数组) 线段树扩展
P3919 【模板】可持久化线段树 1(可持久化数组)
#include#include #include #define R register int using namespace std; const int N=1000009,M=50000009; int P,rt[N],lc[M],rc[M],val[M]; bool nega; void build(R&t,R l,R r)//初始化建树,线段树基本操作 { R m; t=++P; if(l!=r) { m=(l+r)>>1; build(lc[t],l,m); build(rc[t],m+1,r); } else scanf("%d",&val[P]); } inline void insert(R*t,R u,R l,R r,R k)//更新,插入一个新路径 { R m; while(l!=r) { *t=++P; m=(l+r)>>1; if(k<=m)r=m,rc[*t]=rc[u],t=&lc[*t],u=lc[u]; else l=m+1,lc[*t]=lc[u],t=&rc[*t],u=rc[u]; } scanf("%d",&val[*t=++P]); } inline int ask(R t,R l,R r,R k)//询问 { R m; while(l!=r) { m=(l+r)>>1; if(k<=m)r=m,t=lc[t]; else l=m+1,t=rc[t]; } return val[t]; } int main() { R n,m,i,v,op,loc; scanf("%d %d",&n,&m); build(rt[0],1,n); for(i=1;i<=m;++i) { scanf("%d %d %d",&v,&op,&loc); if(op&1)insert(&rt[i],rt[v],1,n,loc); else { cout<<(ask(rt[v],1,n,loc))< 方法二
#includeusing namespace std; const int maxn=1000010; struct kkk{ int l,r,val; }tree[maxn*25]; int a[maxn],root[maxn],n,m,top,rt,mode,x,y; int clone(int node){ top++; tree[top]=tree[node];//全部信息都传到新节点 return top; } int maketree(int node,int begin,int end){ node=++top; if(begin==end){ tree[node].val=a[begin]; return top; } int mid=(begin+end)>>1; tree[node].l=maketree(tree[node].l,begin,mid); tree[node].r=maketree(tree[node].r,mid+1,end); return node; } int update(int node,int begin,int end,int x,int val){ node=clone(node); //更新就要新建节点 if(begin==end){ tree[node].val=val; }else{ int mid=(begin+end)>>1; if(x<=mid) tree[node].l=update(tree[node].l,begin,mid,x,val); //访问左子树 else tree[node].r=update(tree[node].r,mid+1,end,x,val); //访问右子树 } return node; } int query(int node,int begin,int end,int x){ if(begin==end){ return tree[node].val; }else{ int mid=(begin+end)>>1; if(x<=mid) return query(tree[node].l,begin,mid,x); //访问左子树 else return query(tree[node].r,mid+1,end,x); //访问右子树 } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); root[0]=maketree(0,1,n); //root[i]为i版本的根编号,刚开始编号为0 for(int i=1;i<=m;i++){ scanf("%d%d%d",&rt,&mode,&x); if(mode==1){ scanf("%d",&y); root[i]=update(root[rt],1,n,x,y); //保存版本 } else{ printf("%d\n",query(root[rt],1,n,x)); //输出 root[i]=root[rt]; //新建版本 } } }