可持久化数组(可持久化线段树/平衡树)

Posted Z-Y-Y-S

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化数组(可持久化线段树/平衡树)相关的知识,希望对你有一定的参考价值。

题目背景

UPDATE : 最后一个点时间空间已经放大

标题即题意

有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集)

题目描述

如题,你需要维护这样的一个长度为 N N N 的数组,支持如下几种操作

  1. 在某个历史版本上修改某一个位置上的值

  2. 访问某个历史版本上的某一位置的值

此外,每进行一次操作(对于操作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 1iN)。

接下来M M M行每行包含3或4个整数,代表两种操作之一(i i i为基于的历史版本号):

  1. 对于操作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. 对于操作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的结果。

输入输出样例

输入样例#1:
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
输出样例#1:
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 模板可持久化数组(可持久化线段树/平衡树)(入门第一题)

P3919 模板可持久化数组(可持久化线段树/平衡树)

[Luogu 3919]模板可持久化数组(可持久化线段树/平衡树)

[解题报告]P3919 模板可持久化数组(可持久化线段树/平衡树)