P3919 可持久化数组

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));
		}
	}
	
}
几个点:
  1. 主函数里面的root[i] = root[ver],是要保证在op!=1时,不修改线段树结构,只是读取数据。这样,新版本 i 的线段树与旧版本 ver 的线段树完全相同。
  2. change函数里面的u是新建的,并且是实时更新的,v是原来的版本。左右递归的时候,新老树要同时递归。
  3. 董晓老师解法
posted @ 2025-08-30 12:06  Lucian2007  阅读(6)  评论(0)    收藏  举报