可持久化数组(可持久化线段树/平衡树)
Posted Z-Y-Y-S
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化数组(可持久化线段树/平衡树)相关的知识,希望对你有一定的参考价值。
题目背景
UPDATE : 最后一个点时间空间已经放大
标题即题意
有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集)
题目描述
如题,你需要维护这样的一个长度为 N N N 的数组,支持如下几种操作
-
在某个历史版本上修改某一个位置上的值
- 访问某个历史版本上的某一位置的值
此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)
输入输出格式
输入格式:输入的第一行包含两个正整数 N,M N, M N,M, 分别表示数组的长度和操作的个数。
第二行包含N N N个整数,依次为初始状态下数组各位的值(依次为 ai a_i a?i??,1≤i≤N 1 \leq i \leq N 1≤i≤N)。
接下来M M M行每行包含3或4个整数,代表两种操作之一(i i i为基于的历史版本号):
-
对于操作1,格式为vi 1 loci valuei v_i \ 1 \ {loc}_i \ {value}_i v?i?? 1 loc?i?? value?i??,即为在版本vi v_i v?i??的基础上,将 aloci a_{{loc}_i} a?loc?i???? 修改为 valuei {value}_i value?i??
- 对于操作2,格式为vi 2 loci v_i \ 2 \ {loc}_i v?i?? 2 loc?i??,即访问版本vi v_i v?i??中的 aloci a_{{loc}_i} a?loc?i????的值
输出包含若干行,依次为每个操作2的结果。
输入输出样例
5 10 59 46 14 87 41 0 2 1 0 1 1 14 0 1 1 57 0 1 1 88 4 2 4 0 2 5 0 2 4 4 2 1 2 2 2 1 1 5 91
59 87 41 87 88 46
主席树水题
用主席树维护一下每次数组的版本就行
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=1000000; 7 struct Node 8 { 9 int val; 10 Node *ch[2]; 11 }S[N*20],*pos=S; 12 Node *root[N+5]; 13 int a[N+5],b[N+5],n,m,sz,rem[N+5]; 14 void build(Node* &rt,int l,int r) 15 { 16 rt=++pos; 17 if (l==r) 18 {rt->val=a[l]; 19 return; 20 } 21 int mid=(l+r)/2; 22 build(rt->ch[0],l,mid); 23 build(rt->ch[1],mid+1,r); 24 } 25 void insert(Node* &rt,int l,int r,int k,int w) 26 { 27 Node *x=rt; 28 rt=++pos; 29 rt->ch[0]=x->ch[0]; 30 rt->ch[1]=x->ch[1]; 31 if (l==r) 32 {rt->val=w; 33 return; 34 } 35 int mid=(l+r)/2; 36 if (k<=mid) insert(rt->ch[0],l,mid,k,w); 37 else insert(rt->ch[1],mid+1,r,k,w); 38 } 39 int query(Node* rt,int l,int r,int k) 40 { 41 if (l==r) return rt->val; 42 int mid=(l+r)/2; 43 if (mid>=k) return query(rt->ch[0],l,mid,k); 44 else return query(rt->ch[1],mid+1,r,k); 45 } 46 int main() 47 {int i,j,x,y,k,p,v,w; 48 cin>>n>>m; 49 for (i=1;i<=n;i++) 50 { 51 scanf("%d",&a[i]); 52 b[i]=a[i]; 53 } 54 build(root[0],1,n); 55 for (i=1;i<=m;i++) 56 { 57 scanf("%d%d",&p,&v); 58 if (v==1) 59 { 60 scanf("%d%d",&k,&w); 61 root[i]=root[p]; 62 insert(root[i],1,n,k,w); 63 } 64 else 65 { 66 scanf("%d",&k); 67 root[i]=root[p]; 68 printf("%d\n",query(root[i],1,n,k)); 69 } 70 } 71 }
以上是关于可持久化数组(可持久化线段树/平衡树)的主要内容,如果未能解决你的问题,请参考以下文章
luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)
P3919 模板可持久化数组(可持久化线段树/平衡树)(入门第一题)