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

题目背景

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

标题即题意

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

题目描述

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

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

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

此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)

输入输出格式

输入格式:

输入的第一行包含两个正整数 N,M N, M N,M, 分别表示数组的长度和操作的个数。

第二行包含N N N个整数,依次为初始状态下数组各位的值(依次为 ai a_i ai1≤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 vi 1 loci valuei,即为在版本vi v_i vi的基础上,将 aloci a_{{loc}_i} aloci 修改为 valuei {value}_i valuei

  2. 对于操作2,格式为vi 2 loci v_i \ 2 \ {loc}_i vi 2 loci,即访问版本vi v_i vi中的 aloci a_{{loc}_i} aloci的值
输出格式:

输出包含若干行,依次为每个操作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

说明

数据规模:

对于30%的数据:1≤N,M≤103 1 \leq N, M \leq {10}^3 1N,M103

对于50%的数据:1≤N,M≤104 1 \leq N, M \leq {10}^4 1N,M104

对于70%的数据:1≤N,M≤105 1 \leq N, M \leq {10}^5 1N,M105

对于100%的数据:1≤N,M≤106,1≤loci≤N,0≤vi<i,−109≤ai,valuei≤109 1 \leq N, M \leq {10}^6, 1 \leq {loc}_i \leq N, 0 \leq v_i < i, -{10}^9 \leq a_i, {value}_i \leq {10}^91N,M106,1lociN,0vi<i,109ai,valuei109

经测试,正常常数的可持久化数组可以通过,请各位放心

数据略微凶残,请注意常数不要过大

另,此题I/O量较大,如果实在TLE请注意I/O优化

样例说明:

一共11个版本,编号从0-10,依次为:

  • 0 : 59 46 14 87 41

  • 1 : 59 46 14 87 41

  • 2 : 14 46 14 87 41

  • 3 : 57 46 14 87 41

  • 4 : 88 46 14 87 41

  • 5 : 88 46 14 87 41

  • 6 : 59 46 14 87 41

  • 7 : 59 46 14 87 41

  • 8 : 88 46 14 87 41

  • 9 : 14 46 14 87 41

  • 10 : 59 46 14 87 91

思路

其实就是写个可持久化线段树就行了;

会了可持久化数组,就可以进行可持久化并查集的操作了QuQ

代码实现

 1 #include<cstdio>
 2 const int maxn=1e6+10;
 3 int n,m;
 4 int rt[maxn],ts;
 5 int t[maxn<<4],ls[maxn<<4],rs[maxn<<4];
 6 void build(int&k,int l,int r){
 7     k=++ts;
 8     if(l==r){
 9         scanf("%d",&t[k]);
10         return;
11     }
12     int mid=l+r>>1;
13     build(ls[k],l,mid);
14     build(rs[k],mid+1,r);
15 }
16 void change(int q,int&p,int l,int r,int x){
17     p=++ts;
18     if(l==r){
19         scanf("%d",&t[p]);
20         return;
21     }
22     int mid=l+r>>1;
23     if(x<=mid) change(ls[q],ls[p],l,mid,x),rs[p]=rs[q];
24     else change(rs[q],rs[p],mid+1,r,x),ls[p]=ls[q];
25 }
26 int search(int p,int l,int r,int x){
27     if(l==r) return t[p];
28     int mid=l+r>>1;
29     if(x<=mid) return search(ls[p],l,mid,x);
30     else return search(rs[p],mid+1,r,x);
31 }
32 int main(){
33     scanf("%d%d",&n,&m);
34     build(rt[0],1,n);
35     int id,opt,l;
36     for(int i=1;i<=m;i++){
37         scanf("%d%d%d",&id,&opt,&l);
38         if(opt==1) change(rt[id],rt[i],1,n,l);
39         else printf("%d\n",search(rt[id],1,n,l)),rt[i]=rt[id];
40     }
41     return 0;
42 }

 

posted @ 2017-12-28 15:37  J_william  阅读(766)  评论(0编辑  收藏  举报