UPDATE : 最後一個點時間空間已經放大html
標題即題意數組
有了可持久化數組,即可以實現不少衍生的可持久化功能(例如:可持久化並查集)測試
如題,你須要維護這樣的一個長度爲 N N N 的數組,支持以下幾種操做優化
在某個歷史版本上修改某一個位置上的值ui
此外,每進行一次操做(對於操做2,即爲生成一個徹底同樣的版本,不做任何改動),就會生成一個新的版本。版本編號即爲當前操做的編號(從1開始編號,版本0表示初始狀態數組)spa
輸入的第一行包含兩個正整數 N,M N, M N,M, 分別表示數組的長度和操做的個數。code
第二行包含N N N個整數,依次爲初始狀態下數組各位的值(依次爲 ai a_i ai,1≤i≤N 1 \leq i \leq N 1≤i≤N)。htm
接下來M M M行每行包含3或4個整數,表明兩種操做之一(i i i爲基於的歷史版本號):blog
對於操做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的結果。
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
數據規模:
對於30%的數據:1≤N,M≤103 1 \leq N, M \leq {10}^3 1≤N,M≤103
對於50%的數據:1≤N,M≤104 1 \leq N, M \leq {10}^4 1≤N,M≤104
對於70%的數據:1≤N,M≤105 1 \leq N, M \leq {10}^5 1≤N,M≤105
對於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}^91≤N,M≤106,1≤loci≤N,0≤vi<i,−109≤ai,valuei≤109
經測試,正經常數的可持久化數組能夠經過,請各位放心
數據略微兇殘,請注意常數不要過大
另,此題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
其實就是寫個可持久化線段樹就好了;
會了可持久化數組,就能夠進行可持久化並查集的操做了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 }