P3919 【模板】可持久化线段树 1(可持久化数组) 线段树扩展
#include<cstdio>
#include<cstring>
#include<iostream>
#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))<<endl;
rt[i]=++P;//没错,这里的版本复制其实很简单
lc[P]=lc[rt[v]];
rc[P]=rc[rt[v]];
}
}
return 0;
}
方法二
#include<bits/stdc++.h>
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]; //新建版本
}
}
}
浙公网安备 33010602011771号