【转载】【挖掘Treap的潜力】
原帖:
http://fanhq666.blog.163.com/blog/static/819434262011021105212299/
你的Treap能支持以下操作吗?1.区间增减 2.区间求最小 3.区间反转(倒序) 4.区间移动(把一段剪切、粘贴) 不能?只能用splay? 其实,Treap也可以办到。 方法就是:设计把一个子树split成两个子树的算法,以及把两个子树merge的算法。 例:poj3580,代码见最后 另外一个应用:可持久化Treap 设计一个数据结构维护一个序列 插入一个元素 删除一个元素 移动连续的一段(就是剪切、粘贴) *查询m次操作之前的第p个元素是谁 例:超级文本编辑器(我正在构思的一道题) 文本长度不超过100000 每次可以插入、删除、剪切粘贴 要求在线算法 每个操作10微秒时限,一共32M内存 这个可以参见算法导论,核心思想是:一个节点创建之后就不再删除。另外用垃圾回收。 poj3580 #include <cstdio> #include <algorithm> using namespace std; int ran(){ static int x=1364684679; x+=(x<<2)+1; return x; } struct node{ int k,mn,delta,mark,w,sz; node *l,*r; static node* getnew(node *w=NULL){ static node *list=NULL; if (w){ w->r=list;list=w; return NULL; } if (!list){ node *q=new node[10000]; for (int i=0;i<10000;i++){ q[i].w=ran(); q[i].r=list;list=q+i; } } node *p=list;list=list->r; p->l=p->r=NULL;p->delta=p->mark=0; return p; } void down(){ if (mark){ if (l)swap(l->l,l->r),l->mark^=1; if (r)swap(r->l,r->r),r->mark^=1; mark=0; } if (delta){ if (l)l->mn+=delta,l->delta+=delta,l->k+=delta; if (r)r->mn+=delta,r->delta+=delta,r->k+=delta; delta=0; } } void update(){ mn=k; if (l && mn>l->mn+delta)mn=l->mn+delta; if (r && mn>r->mn+delta)mn=r->mn+delta; sz=1; if (l)sz+=l->sz; if (r)sz+=r->sz; } }; #define SIZE(_) ((_)?(_)->sz:0) struct Treap{ node *root; Treap(){root=NULL;} void ins(node *&p,int a,int k){ if (!p){ p=node::getnew(); p->k=p->mn=k;p->sz=1; }else{ p->down(); if (SIZE(p->l)>=a){ ins(p->l,a,k); node *q=p->l; if (q->w<p->w){ q->down(); p->l=q->r;q->r=p;p=q; p->r->update(); } }else{ ins(p->r,a-SIZE(p->l)-1,k); node *q=p->r; if (q->w<p->w){ q->down(); p->r=q->l;q->l=p;p=q; p->l->update(); } } p->update(); } } void ins(int a,int k){ins(root,a,k);} static void merge(node *&p,node *x,node *y){ if (!x || !y){ p=x?x:y; }else if (x->w<y->w){ x->down(); merge(x->r,x->r,y); x->update(); p=x; }else{ y->down(); merge(y->l,x,y->l); y->update(); p=y; } } void del(node *&p,int a){ p->down(); if (SIZE(p->l)==a){ node *q=p; merge(p,p->l,p->r); node::getnew(q); }else if (SIZE(p->l)>a){ del(p->l,a); p->update(); }else{ del(p->r,a-SIZE(p->l)-1); p->update(); } } void del(int a){del(root,a);} static void cut(node *p,node *&x,node *&y,int a){ if (a==0){ x=NULL;y=p; }else if (a==SIZE(p)){ x=p;y=NULL; }else{ p->down(); if (SIZE(p->l)>=a){ y=p; cut(p->l,x,y->l,a); y->update(); }else{ x=p; cut(p->r,x->r,y,a-SIZE(p->l)-1); x->update(); } } } int ask(node *p,int a,int b){ if (a==0 && b==SIZE(p)-1)return p->mn; p->down(); int u=SIZE(p->l); int r=(a<=u && u<=b?p->k:~0u>>1); if (a<u)r=min(r,ask(p->l,a,b>=u?u-1:b)); if (b>u)r=min(r,ask(p->r,a<=u?0:a-u-1,b-u-1)); return r; } int ask(int a,int b){return ask(root,a,b);} void dfs(node *p,int lv){ if (p){ dfs(p->l,lv+1); for (int i=0;i<lv;i++)putchar(' '),putchar(' '); printf("%d %d %d %d %d\n",p->k,p->sz,p->mn,p->delta,p->mark); dfs(p->r,lv+1); } } void dfs(){dfs(root,0);puts("");} }T; void Ins(int a,int k){ //printf("ins %d %d\n",a,k); T.ins(a,k); } void Del(int a){ //printf("del %d\n",a); T.del(a); } void Revolve(int a,int b,int c){ //printf("revolve %d %d %d\n",a,b,c); node *p,*q,*r,*s; Treap::cut(T.root,p,q,a); Treap::cut(q,q,r,b-a+1); Treap::cut(r,r,s,c-b); Treap::merge(p,p,r); Treap::merge(p,p,q); Treap::merge(T.root,p,s); } void Reverse(int a,int b){ //printf("reverse %d %d\n",a,b); node *p,*q,*r; Treap::cut(T.root,p,q,a); Treap::cut(q,q,r,b-a+1); q->mark^=1;swap(q->l,q->r); Treap::merge(p,p,q); Treap::merge(T.root,p,r); } void Add(int a,int b,int c){ //printf("add %d %d %d\n",a,b,c); node *p,*q,*r; Treap::cut(T.root,p,q,a); Treap::cut(q,q,r,b-a+1); //T.dfs(q,0);puts(""); q->k+=c;q->mn+=c;q->delta+=c; //printf("c=%d\n",c); //T.dfs(q,0); //puts(""); Treap::merge(p,p,q); Treap::merge(T.root,p,r); } int Ask(int a,int b){ //printf("ask %d %d\n",a,b); return T.ask(a,b); } int main() { int N; scanf("%d",&N); for (int i=0;i<N;i++){ int x; scanf("%d",&x); Ins(i,x); } int M; //T.dfs(); scanf("%d",&M); char buf[100]; while (M--){ scanf("%s",buf); if (buf[0]=='A'){ int x,y,d; scanf("%d%d%d",&x,&y,&d);x--;y--; Add(x,y,d); //T.dfs(); }else if (buf[0]=='I'){ int x,y; scanf("%d%d",&x,&y); Ins(x,y); }else if (buf[0]=='D'){ int x; scanf("%d",&x);x--; Del(x); }else if (buf[0]=='M'){ int x,y; scanf("%d%d",&x,&y);x--;y--; printf("%d\n",Ask(x,y)); }else if (buf[3]=='E'){ int x,y; scanf("%d%d",&x,&y);x--;y--; Reverse(x,y); }else{ int x,y,t; scanf("%d%d%d",&x,&y,&t);x--;y--; t%=(y-x+1); t+=(y-x+1); t%=(y-x+1); if (t){ Revolve(x,y-t,y); } } } return 0; } 文本编辑器 #include <cstdio> #include <bits/stl_pair.h> #include <queue> #include <deque> #include <algorithm> using namespace std; int ran(){ static int x=222313214; x+=(x<<2)+1; return x; } struct node{ int w,sz; char k; node *l,*r; static node* getnew(node *p=NULL){ static node * list=NULL; if (p){ p->w=ran(); p->r=list;list=p; return NULL; } if (!list){ node *p=new node[10000]; for (int i=0;i<10000;i++){ p[i].r=list;list=p+i; p[i].w=ran(); } } node *q=list; list=list->r; q->l=NULL;q->r=NULL;q->sz=1; return q; } }; #define SIZE(_) ((_)?(_)->sz:0) int M,curid; queue<pair<int,node*> > Literbox; deque<node*> Roots; void giveback(node *p){ Literbox.push(make_pair(curid,p)); } void dfs(node *p,int a,int b){ if (p){ int u=SIZE(p->l); if (u>a)dfs(p->l,a,min(b,u-1)); if (a<=u && u<=b)putchar(p->k); if (b>u)dfs(p->r,max(a-u-1,0),b-u-1); } } node * combine(node *p,node *q){ if (!p || !q)return p?p:q; if (p->w<q->w){ node *a=node::getnew(); a->k=p->k; a->w=p->w; a->sz=p->sz+q->sz; a->l=p->l; a->r=combine(p->r,q); giveback(p); return a; }else{ node *a=node::getnew(); a->k=q->k; a->w=q->w; a->sz=p->sz+q->sz; a->r=q->r; a->l=combine(p,q->l); giveback(q); return a; } } void cutdown(node *p,node *&x,node *&y,int a){ if (a==0)x=NULL,y=p; else if (a==SIZE(p)){ x=p;y=NULL; }else{ if (SIZE(p->l)+1<=a){ x=node::getnew(); x->k=p->k;x->w=p->w; x->sz=a; x->l=p->l; cutdown(p->r,x->r,y,a-SIZE(p->l)-1); giveback(p); }else{ y=node::getnew(); y->k=p->k;y->w=p->w; y->sz=p->sz-a; y->r=p->r; cutdown(p->l,x,y->l,a); giveback(p); } } } void treeadd(node *&p,node *q){ if (!p){ p=q; }else{ if (p->w<q->w){ treeadd(p->r,q); p->sz++; }else{ q->l=p;q->sz=p->sz+1; p=q; } } } void Insert(int i,char a){ node *p=node::getnew(); p->k=a; node *x,*y; cutdown(Roots.back(),x,y,i); x=combine(x,p);x=combine(x,y); Roots.push_back(x); curid++; } void Delete(int i){ node *x,*y,*z; cutdown(Roots.back(),x,y,i); cutdown(y,y,z,1); giveback(y); x=combine(x,z); Roots.push_back(x); curid++; } void Revolve(int a,int b,int c){ node *p,*q,*r,*s; cutdown(Roots.back(),p,q,a); cutdown(q,q,r,b-a+1); cutdown(r,r,s,c-b); p=combine(p,r); p=combine(p,q); p=combine(p,s); Roots.push_back(p); curid++; } void Print(int a,int x,int y){ node *p=Roots.at(Roots.size()-1-a); dfs(p,x,y); puts(""); } void readstr(vector<char> &a){ char c; while (c=getchar(),c==10 || c==13 || c==' '); while (c!=10 && c!=13){ a.push_back(c); c=getchar(); } } int main() { scanf("%d",&M); vector<char> chs; readstr(chs); node *r=NULL; for (int i=0;i<(int)chs.size();i++){ node *p=node::getnew(); p->k=chs[i]; treeadd(r,p); } Roots.push_back(r); curid=0; char cmd[10]; while (scanf("%s",cmd)!=EOF){ if (cmd[0]=='I'){ int x; scanf("%d",&x); scanf("%s",cmd); Insert(x,cmd[0]); }else if (cmd[0]=='D'){ int x; scanf("%d",&x); Delete(x-1); }else if (cmd[0]=='P'){ int x,y,z; scanf("%d%d%d",&x,&y,&z); Print(x,y-1,z-1); }else if (cmd[0]=='C'){ int x,y,z; scanf("%d%d%d",&x,&y,&z); Revolve(x-1,y-1,z-1); } while (!Literbox.empty() && Literbox.front().first<curid-M){ node::getnew(Literbox.front().second); Literbox.pop(); } while ((int)Roots.size()>M)Roots.pop_front(); } return 0; }