loj 120 可持久化序列
https://loj.ac/problem/120
这是一道模板题。
您需要维护一个序列,其中需要提供以下操作:
- 插入一个数到序列的第t版本使其成为序列的第k项,这个数为 x;
- 删除序列的第t版本的第x项;
- 查询序列的第t版本的第x项。
第0个版本为空序列。修改操作不会影响被修改的版本,而总是产生一个新版本。
fhq treap 注意split和merge的时候要新建节点。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=300000+10; 4 int val[N*20],sz[N*20],ch[N*20][2],rt[N],n,sum,cnt,key[N*20]; 5 void inline update(int x){ 6 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 7 } 8 int inline mr(int v){ 9 int x=++cnt;val[x]=v;sz[x]=1;ch[x][0]=ch[x][1]=0;key[x]=rand(); return x; 10 } 11 void inline copy(int x,int y){ 12 val[x]=val[y]; ch[x][0]=ch[y][0];ch[x][1]=ch[y][1];sz[x]=sz[y];key[x]=key[y]; 13 } 14 void split(int now,int k,int &x,int &y){ 15 if(!now) x=y=0; 16 else { 17 if(sz[ch[now][0]]>=k){ 18 y=++cnt;copy(y,now); 19 split(ch[now][0],k,x,ch[y][0]); 20 update(y); 21 }else{ 22 x=++cnt;copy(x,now); 23 split(ch[now][1],k-sz[ch[now][0]]-1,ch[x][1],y); 24 update(x); 25 } 26 } 27 } 28 int merge(int x,int y){ 29 if(!x || !y) return x+y; 30 else { 31 if(key[x]<key[y]){ 32 ch[x][1]=merge(ch[x][1],y); 33 update(x); return x; 34 }else{ 35 ch[y][0]=merge(x,ch[y][0]); 36 update(y); return y; 37 } 38 } 39 } 40 int getkth(int x,int k){ 41 while (x){ 42 if(sz[ch[x][0]]>=k) x=ch[x][0]; 43 else if(sz[ch[x][0]]+1==k) return val[x]; 44 else k-=sz[ch[x][0]]+1,x=ch[x][1]; 45 } 46 } 47 int main(){ 48 scanf("%d",&n); 49 rt[0]=0; 50 int x,y,z,t,k,v,opt; 51 while (n--){ 52 scanf("%d",&opt); 53 if(opt==1){ 54 scanf("%d%d%d",&t,&k,&v); 55 split(rt[++sum]=rt[t],k-1,x,y); 56 rt[sum]=merge(merge(x,mr(v)),y); 57 } 58 if(opt==2){ 59 scanf("%d%d",&t,&k); 60 split(rt[++sum]=rt[t],k,x,y); 61 split(rt[sum],k-1,x,z); 62 rt[sum]=merge(x,y); 63 } 64 if(opt==3){ 65 scanf("%d%d",&t,&k); 66 printf("%d\n",getkth(rt[t],k)); 67 } 68 } 69 return 0; 70 }