感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系
推荐博客:http://memphis.is-programmer.com/posts/46317.html
模板也是摘自这位dalao的
#include<bits/stdc++.h> using namespace std; #define maxn 2000005 #define rep(i,x,y) for(int i=x;i<=y;++i) #define dep(i,x,y) for(int i=x;i>=y;--i) struct Treap{ Treap *l,*r; int fix,key,size; Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1){} inline void updata(){ size=1+(l?l->size:0)+(r?r->size:0); } }*root; typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 Treap *Merge(Treap *A,Treap *B){//合并操作 if(!A)return B; if(!B)return A; if(A->fix<B->fix){ A->r=Merge(A->r,B); A->updata(); return A; } else{ B->l=Merge(A,B->l); B->updata(); return B; } } Droot Split(Treap *x,int k){//拆分操作 if(!x)return Droot(NULL,NULL); Droot y; if(Size(x->l)>=k){ y=Split(x->l,k); x->l=y.second; x->updata(); y.second=x; } else{ y=Split(x->r,k-Size(x->l)-1); x->r=y.first; x->updata(); y.first=x; } return y; } Treap *Build(int *a){//建造操作 static Treap *stack[maxn],*x,*last; int p=0; rep(i,1,a[0]){ x=new Treap(a[i]); last=NULL; while(p && stack[p]->fix>x->fix){ stack[p]->updata(); last=stack[p]; stack[p--]=NULL; } if(p) stack[p]->r=x; x->l=last; stack[++p]=x; } while(p) stack[p--]->updata(); return stack[1]; } int Findkth(int k){//查找第K小 Droot x=Split(root,k-1); Droot y=Split(x.second,1); Treap *ans=y.first; root=Merge(Merge(x.first,ans),y.second); return ans->key; } int Getkth(Treap *x,int v){//询问一个数是第几大 if(!x)return 0; return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1; } void Insert(int v){//插入操作 int k=Getkth(root,v); Droot x=Split(root,k); Treap *n=new Treap(v); root=Merge(Merge(x.first,n),x.second); } void Delete(int k){//删除操作 Droot x=Split(root,k-1); Droot y=Split(x.second,1); root=Merge(x.first,y.second); } int a[maxn],M,x,y; int main(){ scanf("%d",a); rep(i,1,a[0]) scanf("%d",a+i); sort(a+1,a+1+a[0]); root=Build(a); scanf("%d",&M); while(M--){ char ch=getchar(); while(ch!='Q' && ch!='A' && ch!='D') ch=getchar(); scanf("%d",&x); if(ch=='Q') printf("%d ",Findkth(x)); if(ch=='A') Insert(x); if(ch=='D') Delete(x); } }
改了一下之后就A了文艺平衡树
#include<bits/stdc++.h> using namespace std; #define maxn 2000005 #define rep(i,x,y) for(int i=x;i<=y;++i) #define dep(i,x,y) for(int i=x;i>=y;--i) int n; struct Treap{ Treap *l,*r; int fix,key,size; bool fg; Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1){} inline void updata(){ size=1+(l?l->size:0)+(r?r->size:0); } }*root; typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 void pushdown(Treap *x){ if(!x->fg)return; x->fg=0; swap(x->l,x->r); if( x->l ) x->l->fg^=1; if( x->r ) x->r->fg^=1; } Treap *Merge(Treap *A,Treap *B){//合并操作 if(!A)return B; if(!B)return A; pushdown(A);pushdown(B); if(A->fix<B->fix){ A->r=Merge(A->r,B); A->updata(); return A; } else{ B->l=Merge(A,B->l); B->updata(); return B; } } Droot Split(Treap *x,int k){//拆分操作 if(!x)return Droot(NULL,NULL); Droot y; pushdown(x); if(Size(x->l)>=k){ y=Split(x->l,k); x->l=y.second; x->updata(); y.second=x; } else{ y=Split(x->r,k-Size(x->l)-1); x->r=y.first; x->updata(); y.first=x; } return y; } Treap *build(int L,int R){ if(L>R)return NULL; int mid=(L+R)>>1,key=mid-1; Treap *x =new Treap(key); x->l = build(L,mid-1); x->r = build(mid+1,R); x->updata(); return x; } Treap *Build(int *a){//建造操作 static Treap *stack[maxn],*x,*last; int p=0; rep(i,1,a[0]){ x=new Treap(a[i]); last=NULL; while(p && stack[p]->fix>x->fix){ stack[p]->updata(); last=stack[p]; stack[p--]=NULL; } if(p) stack[p]->r=x; x->l=last; stack[++p]=x; } while(p) stack[p--]->updata(); return stack[1]; } void order(Treap *x){ if( x == NULL ) return; pushdown(x); order(x->l); if(x->key >= 1 && x->key<=n)printf("%d ",x->key); order(x->r); } void rev(int L,int R){ Droot tmp1=Split(root,R+1); Droot tmp2=Split(tmp1.first,L); tmp2.second->fg^=1; root = NULL; root = Merge(tmp2.first,tmp2.second); root = Merge(root,tmp1.second); } //int Findkth(int k){//查找第K小 // Droot x=Split(root,k-1); // Droot y=Split(x.second,1); // Treap *ans=y.first; // root=Merge(Merge(x.first,ans),y.second); // return ans->key; //} //int Getkth(Treap *x,int v){//询问一个数是第几大 // if(!x)return 0; // return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1; //} //void Insert(int v){//插入操作 // int k=Getkth(root,v); // Droot x=Split(root,k); // Treap *n=new Treap(v); // root=Merge(Merge(x.first,n),x.second); //} //void Delete(int k){//删除操作 // Droot x=Split(root,k-1); // Droot y=Split(x.second,1); // root=Merge(x.first,y.second); //} //int a[maxn],M,x,y; int M; int main(){ //scanf("%d",a); //rep(i,1,a[0]) scanf("%d",a+i); //sort(a+1,a+1+a[0]); //root=Build(a); scanf("%d",&n); scanf("%d",&M); root=build(1,n+2); int L,R; while(M--){ // char ch=getchar(); // while(ch!='Q' && ch!='A' && ch!='D') ch=getchar(); // scanf("%d",&x); // if(ch=='Q') printf("%d ",Findkth(x)); // if(ch=='A') Insert(x); // if(ch=='D') Delete(x); scanf("%d%d",&L,&R); rev(L,R); } order(root); }
再粘一个非指针版的我敬爱的学长szb写的,浙大一本爷
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; #define mp make_pair typedef pair<int,int> par; const int N=100010; const int inf=1e9; int n,root,cnt; int l[N],r[N],key[N],rnd[N],size[N]; int readin() { int x=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } void update(int x) { size[x]=size[l[x]]+size[r[x]]+1; return; } int merge(int x,int y) { if (!x||!y) return x+y; if (rnd[x]<rnd[y]) { r[x]=merge(r[x],y); update(x); return x; } else { l[y]=merge(x,l[y]); update(y); return y; } } par split(int x,int k) { if (k==0) return mp(0,x); int ls=l[x],rs=r[x]; if (k<=size[l[x]]) { par t=split(l[x],k); l[x]=t.second; update(x); return mp(t.first,x); } else if (k==size[l[x]]+1) { r[x]=0; update(x); return mp(x,rs); } else { par t=split(rs,k-(size[l[x]]+1)); r[x]=t.first; update(x); return mp(x,t.second); } } int query_rank(int x,int k) { int ans=0,t=inf; while(x) { if (k==key[x]) t=min(t,ans+size[l[x]]+1); if (k>key[x]) ans+=(size[l[x]]+1),x=r[x]; else x=l[x]; } return t==inf?ans:t; } void insert(int x) { int k=query_rank(root,x); par t=split(root,k); key[++cnt]=x,rnd[cnt]=rand(),size[cnt]=1; root=merge(t.first,cnt); root=merge(root,t.second); return; } void del(int x) { int k=query_rank(root,x); par t1=split(root,k); par t2=split(t1.first,k-1); root=merge(t2.first,t1.second); return; } int query_num(int x,int k) { while(1) { if (k==size[l[x]]+1) return key[x]; if (k<=size[l[x]]) x=l[x]; else k-=(size[l[x]]+1),x=r[x]; } } int query_pre(int x,int k) { int ans=-inf; while(x) { if (key[x]<k) ans=max(ans,key[x]),x=r[x]; else x=l[x]; } return ans; } int query_sub(int x,int k) { int ans=inf; while(x) { if (key[x]>k) ans=min(ans,key[x]),x=l[x]; else x=r[x]; } return ans; } int main() { int opt,x; n=readin(); for (int i=1;i<=n;i++) { opt=readin(),x=readin(); if (opt==1) insert(x); else if (opt==2) del(x); else if (opt==3) printf("%d ",query_rank(root,x)); else if (opt==4) printf("%d ",query_num(root,x)); else if (opt==5) printf("%d ",query_pre(root,x)); else printf("%d ",query_sub(root,x)); } return 0; }
序列终结者 ,调了好久发现区间截取错了那我咋A的文艺平衡树啊???啊~好像是那个程序建树的时候整个往后串了一位
#include<bits/stdc++.h> using namespace std; #define maxn 2000005 int n; #define inf 1000000000 struct Treap{ Treap *l,*r; int fix,key,size,mx,add; bool fg; Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1),mx(0),fg(0),add(0){} void addv(int w){mx+=w;add+=w;key+=w;} inline void updata(){ size=1+(l?l->size:0)+(r?r->size:0); mx=max(key,max((l?l->mx:-inf),(r?r->mx:-inf))); } }*root; typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 void pushdown(Treap *x){ if(x->fg){ x->fg=0; swap(x->l,x->r); if( x->l ) x->l->fg^=1; if( x->r ) x->r->fg^=1;} if(x->add){ if( x->l ) x->l->addv(x->add); if( x->r ) x->r->addv(x->add); x->add=0; } } Treap *Merge(Treap *A,Treap *B){//合并操作 if(!A)return B; if(!B)return A; pushdown(A);pushdown(B); if(A->fix<B->fix){ A->r=Merge(A->r,B); A->updata(); return A; } else{ B->l=Merge(A,B->l); B->updata(); return B; } } Droot Split(Treap *x,int k){//拆分操作 if(!x)return Droot(NULL,NULL); Droot y; pushdown(x); if(Size(x->l)>=k){ y=Split(x->l,k); x->l=y.second; x->updata(); y.second=x; } else{ y=Split(x->r,k-Size(x->l)-1); x->r=y.first; x->updata(); y.first=x; } return y; } void rev(int L,int R){ Droot tmp1=Split(root,R); Droot tmp2=Split(tmp1.first,L-1); tmp2.second->fg^=1; root = Merge( Merge(tmp2.first,tmp2.second),tmp1.second); } void up(int L,int R,int v){ Droot tmp1=Split(root,R); Droot tmp2=Split(tmp1.first,L-1); tmp2.second->addv(v); root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second); } int query(int L,int R){ Droot tmp1=Split(root,R); Droot tmp2=Split(tmp1.first,L-1); int ret=tmp2.second->mx; root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second); return ret; } int M; int main(){ scanf("%d",&n); scanf("%d",&M); for(int i=1;i<=n;i++){ Treap *a=new Treap(0); root=Merge(root,a); } int L,R; int f,v; while(M--){ scanf("%d",&f); if(f==1){ scanf("%d%d%d",&L,&R,&v); up(L,R,v);} else if(f==2){ scanf("%d%d",&L,&R); rev(L,R); } else { scanf("%d%d",&L,&R); printf("%d ",query(L,R)); } } }