【模板】可持久化數組(可持久化線段樹/平衡樹)

題目背景

UPDATE : 最後一個點時間空間已經放大html

標題即題意數組

有了可持久化數組,即可以實現不少衍生的可持久化功能(例如:可持久化並查集)測試

題目描述

如題,你須要維護這樣的一個長度爲 N N N 的數組,支持以下幾種操做優化

  1. 在某個歷史版本上修改某一個位置上的值ui

  2. 訪問某個歷史版本上的某一位置的值

此外,每進行一次操做(對於操做2,即爲生成一個徹底同樣的版本,不做任何改動),就會生成一個新的版本。版本編號即爲當前操做的編號(從1開始編號,版本0表示初始狀態數組)spa

輸入輸出格式

輸入格式:

輸入的第一行包含兩個正整數 N,M N, M N,M, 分別表示數組的長度和操做的個數。code

第二行包含N N N個整數,依次爲初始狀態下數組各位的值(依次爲 ai a_i ai1≤i≤N 1 \leq i \leq N 1iN)。htm

接下來M M M行每行包含3或4個整數,表明兩種操做之一(i i i爲基於的歷史版本號):blog

  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 valueici

  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 }
相關文章
相關標籤/搜索