题意:维护一个字符串,支持插入字符串,删除连续的一段,查询历史版本的子串,强制在线
本来是用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‘); } } }