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))<

 方法二

#include
using 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];					//新建版本 
		}
	}
}

相关