无旋Treap——从入门到放弃
2017-09-22 15:53
393 查看
前言
已经是从入门到放弃的第四篇了。但是本文并不打算给大家讲无旋Treap复杂度证明一类的。
很显然每次操作都是期望Olog(n)的
什么是Treap?
Treap=Tree+heap其核心思想在于在权值上维护一棵二叉查找树,在优先级上维护一个堆
有旋treap利用旋转操作来维护堆的性质,
而无旋treap利用有序构树维护堆的性质。
无旋Treap的两大构树顺序:权值与原排列
权值构树是很常见的一种构树方法。和有旋treap一样,左儿子与右儿子分别表示比自己小或比自己大的树,同时其优先级均低于该节点。这类问题用有旋treap也能够很好地解决。这样的题有很多,比如bzoj3224普通平衡树但很不幸的是,很多与平衡树沾边的题目大多有维护一个原有有序序列的要求,这个要求基本上就把有旋treap干掉了。但是对于无旋treap,我们可以按原有的序列进行构树,这样就可以维护一个原有的有序排列了。
无旋treap的核心操作:split与merge
但是在构树之后肯定是有修改操作的。这点是毋庸置疑的。对于有旋treap,我们可以通过旋转来插入要加入的权值或是删除对应的节点,但对于可能需要进行区间操作的无旋treap,我们显然不能直接这样做。此时,因为无旋treap的有序性,我们可以像一般的有旋treap一样对需要
插入/删除的部分进行定位查找。
如果是对于权值有序,像普通的有旋treap一样直接递归查找即可,
如果是对于原序列有序,则维护一组指针,也可以很方便地进行查询。
那么在查询到了相应的树中位置之后,我们需要做的就是——
把这棵树拆开
split
整个无旋treap的核心就是它的有序性。在找到了需要操作的位置后,我们可以把这棵树拆成两棵有序的树。
对于查询到的节点,我们根据该节点左儿子的大小对这个节点应该在哪棵树进行判断,然后递归处理即可。
inline D split(Treap* pos,int k){ if(pos==NULL) return D(NULL,NULL); D y; if(sze(pos->son[0])>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-sze(pos->son[0])); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; }
merge
在你进行了加入/删除操作之后,你发现你手上现在有两到三棵树了,自然我们需要将这些树合并。合并的具体操作也是递归处理,此时就可以维护无旋treap的堆性质。但是需要注意的是,合并时两棵树的左右位置,维护的是整棵树的有序性。
inline Treap* merge(Treap* a,Treap* b){ if(!a) return b; if(!b) return a; if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } }
水得如壶口瀑布一样的水题
(1)bzoj3224:普通平衡树题面见链接 传送门
最简单最基础的权值排序外加单点修改查询
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
struct Treap{
Treap* son[2];
int weight,sze,data;
Treap(int v){
sze=1,data=v;weight=rand();
son[1]=son[0]=NULL;
return ;
}
inline void update(){
sze=1+(son[0]!=NULL?son[0]->sze:0)+(son[1]!=NULL?son[1]->sze:0);
return ;
}
}*root;
typedef pair<Treap*,Treap*>D;
inline int sze(Treap* pos){
return pos?pos->sze:0;
}
int n,ord,x;
inline Treap* merge(Treap* a,Treap* b){ if(!a) return b; if(!b) return a; if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } }
inline D split(Treap* pos,int k){ if(pos==NULL) return D(NULL,NULL); D y; if(sze(pos->son[0])>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-sze(pos->son[0])); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; }
inline int getrank(Treap* pos,int x){
if(pos==NULL) return 0;
else return (pos->data>=x)?getrank(pos->son[0],x):getrank(pos->son[1],x)+1+sze(pos->son[0]);
}
inline int getkth(int k){
D x=split(root,k-1);
D y=split(x.second,1);
Treap* pos=y.first;
root=merge(x.first,merge(pos,y.second));
return pos==NULL?0:pos->data;
}
inline void insert(int d){
int k=getrank(root,d);
D x=split(root,k);
Treap* pos=new Treap(d);
root=merge(x.first,merge(pos,x.second));
return ;
}
inline void remove(int d){
int k=getrank(root,d);
D x=split(root,k);
D y=split(x.second,1);
root=merge(x.first,y.second);
return ;
}
signed main(){
n=read();
for(int i=1;i<=n;++i){
ord=read();x=read();
switch(ord){
case 1:insert(x);break;
case 2:remove(x);break;
case 3:write(getrank(root,x)+1);puts("");break;
case 4:write(getkth(x));puts("");break;
case 5:write(getkth(getrank(root,x)));puts("");break;
case 6:write(getkth(getrank(root,x+1)+1));puts("");break;
}
}
return 0;
}
(2)bzoj1503 郁闷的出纳员
题面依然见链接点这里
很明显你不能直接进行全局修改对伐。这个时候你需要打一个差分。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> using namespace std; inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f; } int buf[1024]; inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ; } #define stan 11 struct Treap{ Treap* son[2]; int sze,val,weight; Treap(){val=sze=0,weight=rand();son[1]=son[0]=NULL;} inline void update(){ sze=1+son[0]->sze+son[1]->sze; } }*null=new Treap,*root=null; typedef pair<Treap*,Treap*> D; int m,mini,tmp=0,x,cnt; char ord[stan]; inline Treap* newtreap(int x){ Treap* pos=new Treap(); pos->son[0]=pos->son[1]=null; pos->sze=1;pos->val=x; return pos; } inline Treap* merge(Treap* a,Treap* b){ if(a==null) return b; if(b==null) return a; if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } } inline D split(Treap* pos,int k){ if(pos==null) return D(null,null); D y; if(pos->son[0]->sze>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-pos->son[0]->sze); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; } inline int getrank(Treap* pos,int x){ if(pos==null) return 0; return (pos->val>=x)?getrank(pos->son[0],x):getrank(pos->son[1],x)+1+pos->son[0]->sze; } inline int getkth(int k){ D x=split(root,k-1); D y=split(x.second,1); Treap* pos=y.first; root=merge(x.first,merge(pos,y.second)); return pos->val; } inline void insert(int d){ int k=getrank(root,d); D x=split(root,k); Treap* pos=newtreap(d); root=merge(x.first,merge(pos,x.second)); return ; } inline void remove(){ D x=split(root,1); root=x.second; ++cnt; return ; } signed main(){ m=read();mini=read(); while(m--){ scanf("%s",ord);x=read(); switch(ord[0]){ case 'I':if(x>=mini) insert(x-tmp);break; case 'F':{ if(root==null||root->sze<x) puts("-1"); else{ write(getkth(root->sze-x+1)+tmp); puts(""); } break; } case 'A':tmp+=x;break; case 'S':{ tmp-=x; while(root!=null&&getkth(1)+tmp<mini) remove(); break; } } } write(cnt); return 0; }
(3)bzoj3223文艺平衡树
题面照例见链接点我点我
基础的区间翻转操作,像线段树一样打标记即可
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> using namespace std; inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f; } int buf[1024]; inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ; } #define stan 555555 struct Treap{ Treap* son[2]; int val,weight,sze;bool flip; Treap(){ val=-999999999;sze=0;weight=rand();flip=false; return ; } inline void update(){ sze=son[1]->sze+son[0]->sze+1; return ; } }*null=new Treap(),*root=null,*stack[stan],*x,*last; typedef pair<Treap*,Treap*> D; int n,m,sta,en; inline void maintain_flip(Treap* pos){ if(pos==null) return ; pos->flip^=1; return ; } inline void pushdown(Treap* pos){ if(pos==null) return ; if(pos->flip){ pos->flip^=1; maintain_flip(pos->son[0]); maintain_flip(pos->son[1]); swap(pos->son[0],pos->son[1]); } return ; } inline Treap* newtreap(int val){ Treap *pos=new Treap(); pos->son[1]=pos->son[0]=null;pos->weight=rand(); pos->val=val;pos->sze=1;pos->flip=0; return pos; } inline Treap* merge(Treap* a,Treap* b){ if(a==null) return b; if(b==null) return a; pushdown(a);pushdown(b); if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } } inline D split(Treap* pos,int k){ if(pos==null) return D(null,null); D y;pushdown(pos); if(pos->son[0]->sze>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-pos->son[0]->sze); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; } inline Treap* build(){ int p=0; for(int i=1;i<=n;++i){ x=newtreap(i);last=null; while(p&&stack[p]->weight>x->weight){ stack[p]->update(); last=stack[p]; stack[p--]=null; } if(p) stack[p]->son[1]=x; x->son[0]=last;stack[++p]=x; } while(p) stack[p--]->update(); return stack[1]; } inline void reverse(){ sta=read();en=read(); D x=split(root,sta-1); D y=split(x.second,en-sta+1); maintain_flip(y.first); root=merge(x.first,merge(y.first,y.second)); return ; } inline void write_in_order(Treap* pos){ if(pos==null) return; pushdown(pos); write_in_order(pos->son[0]); write(pos->val);putchar(' '); write_in_order(pos->son[1]); return ; } signed main(){ n=read();m=read(); root=build(); while(m--) reverse(); write_in_order(root); return 0; }
(4)ZJOI2006书架
题面还是点链接吧http://www.lydsy.com/JudgeOnline/problem.php?id=1861
这个地方也是很正常的单点修改,不过注意一下合并的顺序即可
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> using namespace std; inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f; } int buf[1024]; inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ; } typedef unsigned int uint; inline uint nextUint() { static uint seed = 19260817; seed ^= seed << 13; seed ^= seed >> 17; seed ^= seed << 5; return seed; } #define stan 88888 #define sten 11 struct Treap{ Treap* son[2]; Treap* fa; int sze,val; uint weight; Treap(){val=-999999999,sze=0,weight=nextUint(),son[0]=son[1]=fa=this;} inline void update(){ sze=son[0]->sze+son[1]->sze+1; son[0]->fa=son[1]->fa=this; } }*null=new Treap(),*root=null,*stack[stan],*x,*last,*posi[stan]; typedef pair<Treap*,Treap*> D; int n,m,s,u,a[stan]; char ord[sten]; inline Treap* newtreap(int val){ Treap* pos=new Treap(); pos->son[1]=pos->son[0]=pos->fa=null; pos->sze=1;pos->val=val;pos->weight=nextUint(); return pos; } inline Treap* merge(Treap* a,Treap* b){ if(a==null) return b; if(b==null) return a; if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } } inline D split(Treap* pos,int k){ if(pos==null) return D(null,null); D y; if(pos->son[0]->sze>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-pos->son[0]->sze); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; } inline Treap* build(){ int p=0; for(int i=1;i<=n;++i){ a[i]=read(); posi[a[i]]=x=newtreap(a[i]);last=null; while(p&&stack[p]->weight>x->weight){ stack[p]->update(); last=stack[p]; stack[p--]=null; } if(p) stack[p]->son[1]=x;x->fa=stack[p]; x->son[0]=last;last->fa=x; stack[++p]=x; } while(p) stack[p--]->update(); return stack[1]; } inline int getrank(Treap* pos){ int ret=pos->son[0]->sze; while(pos->fa!=null&&pos->fa!=NULL){ if(pos==pos->fa->son[1]) ret+=pos->fa->son[0]->sze+1; pos=pos->fa; } return ret; } inline void addhead(int x){ int k=getrank(posi[x]); D X=split(root,k); D y=split(X.second,1); root=merge(y.first,merge(X.first,y.second)); return ; } inline void addtail(int x){ int k=getrank(posi[x]); D X=split(root,k); D y=split(X.second,1); root=merge(X.first,merge(y.second,y.first)); return ; } void addmid(int xxx,int opt) { if(!opt) return ; static D X,y,z; int k=getrank(posi[xxx]); X=split(root, k); y=split(X.second,1); if(opt==-1)X=split(X.first,X.first->sze-1), root=merge(merge(X.first,y.first),merge(X.second,y.second)); else z=split(y.second,1), root=merge(merge(X.first,z.first),merge(y.first,z.second)); } inline int getkth(int k){ D X=split(root,k-1); D y=split(X.second,1); Treap* pos=y.first; root=merge(X.first,merge(pos,y.second)); return pos->val; } signed main(){ n=read();m=read(); root=build(); while(m--){ scanf("%s",ord);s=read(); switch(ord[0]){ case 'T':addhead(s);break; case 'B':addtail(s);break; case 'I':u=read();addmid(s,u);break; case 'A':write(getrank(posi[s]));puts("");break; case 'Q':write(getkth(s));puts("");break; } } return 0; }
(5)CQOI2014排序机械臂
题面还是有链接就是这里
很中规中矩的不固定排列序+区间修改
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> using namespace std; inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f; } int buf[1024]; inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ; } typedef unsigned int uint; inline uint nxtunit(){ static uint seed=19260817; seed^=seed<<13; seed^=seed>>17; seed^=seed<<5; return seed; } #define stan 111111 struct Treap{ Treap* son[2]; Treap* fa; int sze,val; uint weight; bool flip; Treap(){val=-999999999,sze=0,weight=nxtunit(),son[0]=son[1]=fa=this;flip=false;} inline void update(){ sze=son[0]->sze+son[1]->sze+1; son[0]->fa=son[1]->fa=this; } }*null=new Treap(),*root=null,*stack[stan],*x,*last,*posi[stan]; typedef pair<Treap*,Treap*> D; int n,m,s,u,a[stan],to[stan]; struct thing{ int ord,val; }thi[stan]; inline bool cmp(const thing &a,const thing &b){ if(a.val!=b.val) return a.val<b.val; else return a.ord<b.ord; } inline Treap* newtreap(int val){ Treap* pos=new Treap(); pos->son[1]=pos->son[0]=pos->fa=null; pos->sze=1;pos->val=val;pos->weight=nxtunit(); pos->flip=false; return pos; } inline void pushdown(Treap* pos){ if(pos==null||pos==NULL) return ; if(pos->flip){ pos->flip^=1; pos->son[0]->flip^=1; pos->son[1]->flip^=1; swap(pos->son[0],pos->son[1]); } return ; } inline Treap* merge(Treap* a,Treap* b){ if(a==null) return b; if(b==null) return a; pushdown(a);pushdown(b); if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } } inline D split(Treap* pos,int k){ if(pos==null) return D(null,null); D y;pushdown(pos); if(pos->son[0]->sze>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-pos->son[0]->sze); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; } inline void rotate(Treap* pos){ if(pos==null||pos==NULL) return ; rotate(pos->fa); pushdown(pos); return ; } inline int getrank(Treap* pos){ rotate(pos); int ret=pos->son[0]->sze+1; while(pos->fa!=null&&pos->fa!=NULL){ if(pos==pos->fa->son[1]) ret+=pos->fa->son[0]->sze+1; pos=pos->fa; } return ret; } inline int getans(int d){ int ret=getrank(posi[d]); D x=split(root,ret); D y=split(x.first,d-1); y.second->flip^=1; root=merge(merge(y.first,y.second),x.second); return ret; } signed main(){ n=read(); for(int i=1;i<=n;++i){ a[i]=read();thi[i].ord=i;thi[i].val=a[i]; } sort(thi+1,thi+n+1,cmp); for(int i=1;i<=n;++i) to[thi[i].ord]=i; for(int i=1;i<=n;++i){ posi[to[i]]=newtreap(a[i]); root=merge(root,posi[to[i]]); } for(int i=1;i<n;++i){ write(getans(i)); putchar(' '); } write(getans(n)); return 0; }
(6) NOI2005维修数列
题面在这里
如果你上面五道题都A了,这个题也不难想
写就是另一回事了
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> using namespace std; inline int read(){ int i=0,f=1; char ch; for(ch=getchar();!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) i=(i<<3)+(i<<1)+(ch^48); return i*f; } int buf[1024]; inline void write(int x){ if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]) putchar(buf[buf[0]--]+48); return ; } #define stan 555555 struct Treap{ Treap* son[2]; int val,weight,sze,sum,l,r,m;bool flip,mark; Treap(){val=l=r=m=-999999999,sum=sze=0;mark=flip=0;weight=rand();} inline void update(){ sze=son[1]->sze+son[0]->sze+1; sum=son[1]->sum+son[0]->sum+val; l=max(son[0]->l,max(son[0]->sum+val,son[0]->sum+val+son[1]->l)); r=max(son[1]->r,max(son[1]->sum+val,son[1]->sum+val+son[0]->r)); m=max(son[0]->m,max(max(0,son[0]->r)+val+max(0,son[1]->l),son[1]->m)); } }*null=new Treap(),*root=null,*stack[stan],*x,*last; typedef pair<Treap*,Treap*> D; int n,m,a[stan]; char ord[stan]; inline void maintain_flip(Treap* pos){ if(pos==null) return ; pos->flip^=1;swap(pos->l,pos->r); return ; } inline void maintain_mark(Treap* pos,int c){ if(pos==null) return ; pos->val=c;pos->sum=pos->sze*c; pos->l=pos->r=pos->m=max(pos->sze*c,c); pos->mark=true; return ; } inline void pushdown(Treap *pos){ if(pos==null) return ; if(pos->flip){ pos->flip^=1; maintain_flip(pos->son[0]); maintain_flip(pos->son[1]); swap(pos->son[0],pos->son[1]); } if(pos->mark){ maintain_mark(pos->son[0],pos->val); maintain_mark(pos->son[1],pos->val); pos->mark=0; } return ; } inline Treap* newtreap(int val) { Treap *pos=new Treap(); pos->son[1]=pos->son[0]=null;pos->weight=rand(); pos->val=pos->sum=val;pos->sze=1;pos->flip=pos->mark=0; pos->m=pos->l=pos->r=val; return pos; } Treap* merge(Treap* a,Treap* b){ if(a==null) return b; if(b==null) return a; pushdown(a);pushdown(b); if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } } D split(Treap* pos,int k){ if(pos==null) return D(null,null); D y;pushdown(pos); if(pos->son[0]->sze>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-pos->son[0]->sze); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; } inline Treap* build(){ int p=0; for(int i=1;i<=n;++i){ a[i]=read(); x=newtreap(a[i]);last=null; while(p&&stack[p]->weight>x->weight){ stack[p]->update(); last=stack[p]; stack[p--]=null; } if(p) stack[p]->son[1]=x; x->son[0]=last;stack[++p]=x; } while(p) stack[p--]->update(); return stack[1]; } inline void adjust(Treap *pos){ if(pos==null) return; if(pos->son[0]!=null) adjust(pos->son[0]); if(pos->son[1]!=null) adjust(pos->son[1]); delete pos;return ; } inline void insert(){ int sta;sta=read();n=read(); Treap* pos=build(); D x=split(root,sta); root=merge(x.first,merge(pos,x.second)); return ; } inline void remove(){ int sta;sta=read();n=read(); D x=split(root,sta-1); D y=split(x.second,n); adjust(y.first); root=merge(x.first,y.second); return ; } inline void reverse(){ int sta;sta=read();n=read(); D x=split(root,sta-1); D y=split(x.second,n); maintain_flip(y.first); root=merge(x.first,merge(y.first,y.second)); return ; } inline void make_same(){ int sta,c;sta=read();n=read();c=read(); D x=split(root,sta-1); D y=split(x.second,n); maintain_mark(y.first,c); root=merge(x.first,merge(y.first,y.second)); return ; } inline int get_sum(){ int sta;sta=read();n=read(); if(n==0) return 0; D x=split(root,sta-1); D y=split(x.second,n); int ret=y.first->sum; root=merge(x.first,merge(y.first,y.second)); return ret; } signed main(){ n=read();m=read(); root=build(); while(m--){ scanf("%s",ord); switch(ord[0]){ case 'I':{insert();break;} case 'D':{remove();break;} case 'M':{ if(ord[2]=='K'){make_same();break;} else {write(root->m);puts("");break;} } case 'G':{write(get_sum());puts("");break;} case 'R':{reverse();break;} } } return 0; }
小结
终于是又水了一篇其实我觉得LadyLex的讲解才是坠吼的传送门
%%%LadyLex
同时感谢Xehoth大佬在看到我在内网莫名血T之后甩给了我一个强大的随机数生成器
%%%Xehoth
相关文章推荐
- 《React从入门到放弃》 第二集 JSX
- robotium从入门到放弃 一 测试开发环境搭建
- 翻身的废鱼——论PHP从入门到放弃需要多久?8
- cucumber从入门到放弃
- [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
- treap入门题。。
- React-Native从入门到放弃(一)准备篇
- 《Java从入门到放弃》JavaSE入门篇:变量
- CYQ.Data V5 从入门到放弃ORM系列:教程 - MProc类使用
- Html-Css 从入门到放弃(一)基础知识
- RxJava2.0 从入门到放弃?
- Android-框架-Dagger2-Dagger2从入门到放弃再到恍然大悟
- Android开发从入门到放弃(9)使用ListView显示一个类的数组
- react 入门到放弃 之 webpack
- MySQL从入门到放弃第三章:约束
- 入门到放弃之node系列Hello Word篇
- Android开发从入门到放弃(10)适配GridView
- Python从入门到放弃(Mac) - Hello World(从安装到你的第一个程序)
- Jersey入门到放弃-2
- 算法与数据结构,从入门到不放弃~