可持久化数据结构(模板)

推荐博客:

可持久化数组:https://blog.csdn.net/chenxiaoran666/article/details/81503323

可持久化并查集:https://blog.csdn.net/chenxiaoran666/article/details/81505870

https://www.cnblogs.com/peng-ym/p/9357220.html

模板:

1,可持久化数组

luogu3919:https://www.luogu.org/problem/P3919

题意:有一个数列,支持在原来的某一版本查询位置为$loc$的值;修改某一版本位置为$loc$的值为$xx$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e6+10; 
 4 struct node{
 5     int l,r; int val;
 6 }tree[maxn*100];
 7 int root[maxn],a[maxn],sz=0;
 8 void build(int &x,int l,int r){
 9     x=++sz;
10     if (l==r){
11         tree[x].val=a[l];
12         return ;
13     }
14     int mid=(l+r)>>1;
15     build(tree[x].l,l,mid);
16     build(tree[x].r,mid+1,r);
17 }
18 void update(int &x,int y,int l,int r,int dex,int val){
19     x=++sz; tree[x]=tree[y];
20     if (l==r){
21         tree[x].val=val;
22         return ;
23     }
24     int mid=(l+r)>>1;
25     if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex,val);
26     else update(tree[x].r,tree[y].r,mid+1,r,dex,val);
27 }
28 int query(int x,int l,int r,int xx){
29     if (l==r) return tree[x].val;
30     int mid=(l+r)>>1;
31     if (xx<=mid) return query(tree[x].l,l,mid,xx);
32     else return query(tree[x].r,mid+1,r,xx);
33 }
34 int main(){
35     int n,m,v,xx,x,y;scanf("%d%d",&n,&m);
36     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
37     build(root[0],1,n);
38     for (int i=1;i<=m;i++){
39         scanf("%d%d",&v,&xx);
40         if (xx==1){
41             scanf("%d%d",&x,&y);
42             update(root[i],root[v],1,n,x,y);
43         }
44         else{
45             scanf("%d",&x);
46             root[i]=root[v];
47             int ans=query(root[i],1,n,x);
48             printf("%d\n",ans);
49         }
50     }
51     return 0;
52 }
可持久化数组

2,可持久化并查集

luogu3402:https://www.luogu.org/problem/P3402

题意:初始有$n$个集合,进行$m$次操作:$1  a   b$合并a,b所在集合;$2   k$回到第k次操作之后的状态(查询算作操作);$3   a   b$询问a,b是否属于同一集合,是则输出1否则输出0。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 struct node{
 5     int l,r,fa,level;
 6 }tree[maxn*100];
 7 int root[maxn],sz=0,n,m;
 8 void build(int &x,int l,int r){
 9     x=++sz;
10     if (l==r){
11         tree[x].fa=l;
12         return ;
13     }
14     int mid=(l+r)>>1;
15     build(tree[x].l,l,mid);
16     build(tree[x].r,mid+1,r);
17 }
18 void update(int &x,int y,int l,int r,int xx,int fa){
19     x=++sz; tree[x]=tree[y];
20     if (l==r){
21         tree[x].fa=fa;
22         return ;
23     } 
24     int mid=(l+r)>>1;
25     if (xx<=mid) update(tree[x].l,tree[x].l,l,mid,xx,fa);
26     else update(tree[x].r,tree[y].r,mid+1,r,xx,fa);
27 }
28 void add_level(int x,int l,int r,int xx){
29     if (l==r){
30         tree[x].level++;
31         return ;
32     }
33     int mid=(l+r)>>1;
34     if (xx<=mid) add_level(tree[x].l,l,mid,xx);
35     else add_level(tree[x].r,mid+1,r,xx);
36 }
37 int query(int x,int l,int r,int xx){
38     if (l==r) return x;
39     int mid=(l+r)>>1;
40     if (xx<=mid) query(tree[x].l,l,mid,xx);
41     else query(tree[x].r,mid+1,r,xx);
42 }
43 int find(int root,int x){  //询问x在root版本下的祖先 
44     int fa=query(root,1,n,x);
45     if (tree[fa].fa==x) return fa;
46     else return find(root,tree[fa].fa);
47 }
48 int main(){
49     int xx,x,y;scanf("%d%d",&n,&m);
50     build(root[0],1,n);
51     for (int i=1;i<=m;i++){
52         scanf("%d",&xx);
53         if (xx==1){
54             scanf("%d%d",&x,&y);
55             root[i]=root[i-1];
56             int fx=find(root[i],x),fy=find(root[i],y);
57             if (fx!=fy){
58                 if (tree[fx].level<tree[fy].level) swap(fx,fy);
59                 update(root[i],root[i-1],1,n,tree[fy].fa,tree[fx].fa);//按秩合并 
60                 if (tree[fx].level==tree[fy].level) add_level(root[i],1,n,tree[fx].fa);
61             }
62         }
63         else if (xx==2){
64             scanf("%d",&x);
65             root[i]=root[x];
66         }
67         else{
68             scanf("%d%d",&x,&y);
69             root[i]=root[i-1];
70             int fx=find(root[i],x),fy=find(root[i],y);
71             if (fx==fy) printf("1\n"); else printf("0\n");
72         }
73     }
74     return 0;
75 }
可持久化并查集

 

posted @ 2019-09-05 14:17  Changer-qyz  阅读(246)  评论(0编辑  收藏  举报