函数式treap也就是可持久化treap,是一种可持久化数据结构。它的主要操作是merge和split,详情可以参考不基于旋转的treap。
不同之处在于我们要可持久化,所以只要将所有的修改操作变为建新节点就行了。写起来很简单,具体实现可以看看例题代码。
UVA12538
题意就是要求维护一个字符串,支持插入,修改,访问历史版本。
这直接用函数式treap做就可以了。
我的实现方法与不同treap不同的在于,合并是我是按子树大小随机合并的,具体操作参见代码。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
typedef pair<int,int>p;
typedef long long ll;
struct node{
int data,ls,rs,size;
}t[10000010];
int root[50010],cnt,n,x,y,z,op,tot,nc;
char s[1000010];
#define updata(x) t[x].size=t[t[x].ls].size+t[t[x].rs].size+1
p split(int x,int y){
if(x==0) return make_pair(0,0);
int num=++cnt;
t[num]=t[x]; //建新节点
if(t[t[x].ls].size==y){
t[num].ls=0; updata(num);
return make_pair(t[x].ls,num);
}
if(t[t[x].ls].size+1==y){
t[num].rs=0; updata(num);
return make_pair(num,t[x].rs);
}
if(t[t[x].ls].size>y){
p tmp=split(t[x].ls,y);
t[num].ls=tmp.second; updata(num);
return make_pair(tmp.first,num);
}
p tmp=split(t[x].rs,y-t[t[x].ls].size-1);
t[num].rs=tmp.first; updata(num);
return make_pair(num,tmp.second);
}
int merge(int x,int y){
if(x==0||y==0) return x+y;
if((ll)t[x].size*1107>=(ll)rand()%1107*(ll)(t[x].size+t[y].size)){
//按子树大小合并
int tmp=++cnt; t[tmp]=t[x]; //新建节点
t[tmp].rs=merge(t[x].rs,y);
updata(tmp); return tmp;
}
int tmp=++cnt; t[tmp]=t[y]; //新建节点
t[tmp].ls=merge(x,t[y].ls);
updata(tmp); return tmp;
}
int make(int l,int r,char s[]){
if(l>r) return 0;
int mid=(l+r)>>1;
int tmp=++cnt;
t[tmp].data=s[mid]-'a';
t[tmp].ls=make(l,mid-1,s);
t[tmp].rs=make(mid+1,r,s);
updata(tmp); return tmp;
}
void print(int x){
if(t[x].ls) print(t[x].ls);
putchar(t[x].data+'a');
if(t[x].data==2) nc++;
if(t[x].rs) print(t[x].rs);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%s",&x,s); x-=nc;
p tmp=split(root[tot],x);
root[++tot]=merge(tmp.first,make(0,strlen(s)-1,s));
root[tot]=merge(root[tot],tmp.second);
} else
if(op==2){
scanf("%d%d",&x,&y); x-=nc; y-=nc;
p t1=split(root[tot],y+x-1);
p t2=split(t1.first,x-1);
root[++tot]=merge(t2.first,t1.second);
}else{
scanf("%d%d%d",&x,&y,&z);
x-=nc; y-=nc; z-=nc;
p t1=split(root[x],z+y-1);
p t2=split(t1.first,y-1);
print(t2.second);
putchar('\n');
}
}
return 0;
}