P3919
点击查看代码
#include<bits/stdc++.h>
#define N 1000005
#define mid ((l+r)>>1)
using namespace std;
int n,m,a[N];
int root[N],tot;//根节点,节点个数
int ls[N*25],rs[N*25],val[N*25];
void build(int &u,int l,int r)
{
u=++tot;//动态开点
if(l==r)
{
val[u]=a[l];
return;
}
build(ls[u],l,mid);
build(rs[u],mid+1,r);
}
void change(int &u,int v,int l,int r,int p,int x)
{
u=++tot;
ls[u]=ls[v]; rs[u]=rs[v] ;val[u]=val[v];
if(l==r)
{
val[u]=x;
return;
}
if(p<=mid) change(ls[u],ls[v],l,mid,p,x);
else change(rs[u],rs[v],mid+1,r,p,x);
}
int query(int u,int l,int r,int p)
{
if(l==r) return val[u];
if(p<=mid) return query(ls[u],l,mid,p);
else return query(rs[u],mid+1,r,p);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(root[0],1,n);
for(int i=1;i<=m;i++)
{
int ver,op,p,x;
scanf("%d%d",&ver,&op);
if(op==1)
{
scanf("%d%d",&p,&x);
change(root[i],root[ver],1,n,p,x);
}
else
{
scanf("%d",&p);
root[i]=root[ver];
printf("%d\n",query(root[ver],1,n,p));
}
}
}
几个点:
- 主函数里面的
root[i] = root[ver],是要保证在op!=1时,不修改线段树结构,只是读取数据。这样,新版本 i 的线段树与旧版本 ver 的线段树完全相同。
- change函数里面的u是新建的,并且是实时更新的,v是原来的版本。左右递归的时候,新老树要同时递归。
- 董晓老师解法