模板代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define mid ((l+r)>>1)
const int INF=1e9+7,MAXNODE=24e6+7,MAXN=1e6+7;
int N,M,tmp[MAXN],rt[MAXN];
int val[MAXNODE],lson[MAXNODE],rson[MAXNODE],sz;
void init(int &x,int l,int r){
x=++sz;
if(l==r){
val[x]=tmp[l];
return;
}
init(lson[x],l,mid);
init(rson[x],mid+1,r);
}
void modify(int &x,int l,int r,int p,int q,int v){
x=++sz;
if(l==r){
val[x]=v;
return;
}
lson[x]=lson[p];
rson[x]=rson[p];
val[x]=val[p];
if(q<=mid)
modify(lson[x],l,mid,lson[p],q,v);
else
modify(rson[x],mid+1,r,rson[p],q,v);
}
int query(int x,int l,int r,int q){
if(l==r)
return val[x];
if(q<=mid)
return query(lson[x],l,mid,q);
return query(rson[x],mid+1,r,q);
}
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
scanf("%d",tmp+i);
init(rt[0],1,N);
for(int i=1;i<=M;i++){
int edit/*edition*/,oper,loc/*location*/,v/*value*/;
scanf("%d%d%d",&edit,&oper,&loc);
if(oper==1){
scanf("%d",&v);
modify(rt[i],1,N,rt[edit],loc,v);
}else{
printf("%d\n",query(rt[edit],1,N,loc));
rt[i]=rt[edit];
}
}
return 0;
}
原题链接题面:


可持久化数组实现
1.结构:主席树
2.思想:对于每一个版本的数组建一棵线段树,因为相邻版本差异为一个数字,所以单次修改时间空间复杂度均为O(logN)
3.实现
- 先定义一些数组(主席树的常规成员):
-
const int MAXN数字个数,MAXNODE节点个数(2*N+NlogN) int N数字个数,M查询个数,tmp[MAXN]读入数值暂存数组,rt[MAXN]每个版本的线段树的根; int val[MAXNODE]线段树值,lson[MAXNODE]左儿子,rson[MAXNODE]右儿子,sz节点栈顶;
- 初始化
- 读入并建树,将版本为0的线段树为初始树根
-
scanf("%d%d",&N,&M); for(int i=1;i<=N;i++) scanf("%d",tmp+i); init(rt[0],1,N);按照动态开点线段树常规方法建树
void init(int &x,int l,int r){ x=++sz; if(l==r){ val[x]=tmp[l]; return; } init(lson[x],l,mid); init(rson[x],mid+1,r); }
- 更新
-
void modify(int &x当前节点下标,int l,int r,int p上一个版本,int q要赋值的位置,int v值){ x=++sz; if(l==r){找到节点,赋值并退出 val[x]=v; return; } lson[x]=lson[p];复制上一个版本的节点信息 rson[x]=rson[p]; val[x]=val[p]; if(q<=mid)按照动态开点线段树遍历 modify(lson[x],l,mid,lson[p],q,v); else modify(rson[x],mid+1,r,rson[p],q,v); } - 查询:常规线段树查询
-
int query(int x当前点下标,int l,int r,int q查询位置){ if(l==r) return val[x]; if(q<=mid) return query(lson[x],l,mid,q); return query(rson[x],mid+1,r,q); }
完整代码:

1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long LL;
4 #define mid ((l+r)>>1)
5 const int INF=1e9+7,MAXNODE=24e6+7,MAXN=1e6+7;
6 int N,M,tmp[MAXN],rt[MAXN];
7 int val[MAXNODE],lson[MAXNODE],rson[MAXNODE],sz;
8 void init(int &x,int l,int r){
9 x=++sz;
10 if(l==r){
11 val[x]=tmp[l];
12 return;
13 }
14 init(lson[x],l,mid);
15 init(rson[x],mid+1,r);
16 }
17 void modify(int &x,int l,int r,int p,int q,int v){
18 x=++sz;
19 if(l==r){
20 val[x]=v;
21 return;
22 }
23 lson[x]=lson[p];
24 rson[x]=rson[p];
25 val[x]=val[p];
26 if(q<=mid)
27 modify(lson[x],l,mid,lson[p],q,v);
28 else
29 modify(rson[x],mid+1,r,rson[p],q,v);
30 }
31 int query(int x,int l,int r,int q){
32 if(l==r)
33 return val[x];
34 if(q<=mid)
35 return query(lson[x],l,mid,q);
36 return query(rson[x],mid+1,r,q);
37 }
38 int main(){
39 scanf("%d%d",&N,&M);
40 for(int i=1;i<=N;i++)
41 scanf("%d",tmp+i);
42 init(rt[0],1,N);
43 for(int i=1;i<=M;i++){
44 int edit/*edition*/,oper,loc/*location*/,v/*value*/;
45 scanf("%d%d%d",&edit,&oper,&loc);
46 if(oper==1){
47 scanf("%d",&v);
48 modify(rt[i],1,N,rt[edit],loc,v);
49 }else{
50 printf("%d\n",query(rt[edit],1,N,loc));
51 rt[i]=rt[edit];
52 }
53 }
54 return 0;
55 }
来源:https://www.cnblogs.com/guoshaoyang/p/10924416.html

