题意:维护一个字符串,支持插入字符串,删除连续的一段,查询历史版本的子串,强制在线
本来是用rope可以水过的,但是想拿来试水可持久化treap
几乎跟普通treap完全一样,只不过是merge和split时要相应地复制节点,注意是复制不是直接新建
建树得用笛卡尔树了TT,其实挺好理解的,最后记得全部pushup并退栈就好
决定了!以后写可持久化treap都用指针,挺优秀啊w
p.s.UVa真的太慢啦,机房的辣鸡网络不太兹磁这个网站
srand(time(0))无用论?
#include<stdio.h>
#include<stdlib.h>
struct treap{
treap*l,*r;
int siz,fix;
char c;
void update(){siz=1+(l?l->siz:0)+(r?r->siz:0);}
treap(char v){
c=v;
fix=rand()*rand();
l=r=0;
siz=1;
}
treap(treap*t){
*this=*t;
}
}*rt[50010],*stk[1000010];
char s[1000010];
int siz(treap*x){return x?x->siz:0;}
treap*build(){
int top=0,i;
treap*x,*las;
for(i=0;s[i];i++){
x=new treap(s[i]);
las=0;
while(top&&stk[top]->fix>x->fix){
stk[top]->update();
las=stk[top];
top--;
}
if(top)stk[top]->r=x;
x->l=las;
top++;
stk[top]=x;
}
while(top){
stk[top]->update();
top--;
}
return stk[1];
}
struct pair{
treap*l,*r;
pair(treap*a=0,treap*b=0){l=a;r=b;}
};
pair split(treap*x,int k){
if(x==0)return pair();
pair s;
treap*n;
n=new treap(x);
if(k<=siz(x->l)){
s=split(n->l,k);
n->l=s.r;
s.r=n;
}else{
s=split(n->r,k-siz(x->l)-1);
n->r=s.l;
s.l=n;
}
n->update();
return s;
}
treap*merge(treap*a,treap*b){
if(a==0&&b==0)return 0;
if(a==0)return new treap(b);
if(b==0)return new treap(a);
treap*x;
if(a->fixfix){
x=new treap(a);
x->r=merge(x->r,b);
}else{
x=new treap(b);
x->l=merge(a,x->l);
}
x->update();
return x;
}
int ccnt;
void dfs(treap*x){
if(x->l)dfs(x->l);
if(x->c==‘c‘)ccnt++;
putchar(x->c);
if(x->r)dfs(x->r);
}
int main(){
int m,i,x,y,z,cnt;
pair p,q;
scanf("%d",&m);
cnt=0;
while(m--){
scanf("%d",&i);
if(i==1){
scanf("%d%s",&x,s);
x-=ccnt;
p=split(rt[cnt],x);
cnt++;
rt[cnt]=merge(p.l,merge(build(),p.r));
}
if(i==2){
scanf("%d%d",&x,&y);
x-=ccnt;
y-=ccnt;
p=split(rt[cnt],x-1);
q=split(p.r,y);
cnt++;
rt[cnt]=merge(p.l,q.r);
}
if(i==3){
scanf("%d%d%d",&x,&y,&z);
x-=ccnt;
y-=ccnt;
z-=ccnt;
p=split(rt[x],y-1);
q=split(p.r,z);
dfs(q.l);
putchar(‘\n‘);
}
}
}