bzoj3224Tyvj 1728 普通平衡树 平衡树的三种姿势 :splay,Treap,ScapeGoat_Tree
Posted TS_Hugh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3224Tyvj 1728 普通平衡树 平衡树的三种姿势 :splay,Treap,ScapeGoat_Tree相关的知识,希望对你有一定的参考价值。
直接上代码 正所谓 人傻自带大常数
平衡树的几种姿势: AVL Red&Black_Tree 码量爆炸,不常用;SBT 出于各种原因,不常用。
常用:
Treap 旋转 基于旋转操作和随机数堆 但不支持区间操作。
非旋转 基于随机数堆和拆分合并操作 常数较大
Spaly 完全基于旋转 各种操作
ScapeGoat_Tree 基于a权值平衡树和压扁重构 无旋转 但不支持区间操作
PS:非旋转可以实现平衡树的可持久化,从而来套一些东西
splay
#include<cstdio> #define MAXN 200005 using namespace std; int key[MAXN],ch[MAXN][2],cnt[MAXN],size[MAXN],f[MAXN],n,sz,root; inline void clear(int x) { key[x]=ch[x][0]=ch[x][1]=cnt[x]=size[x]=f[x]=0; return; } inline int get(int x) { return ch[f[x]][1]==x; } inline void update(int x) { size[x]=cnt[x]+size[ch[x][1]]+size[ch[x][0]]; return; } inline void rotate(int x) { int fa=f[x],pa=f[fa],what=get(x); if(pa){ch[pa][fa==ch[pa][1]]=x;} ch[fa][what]=ch[x][what^1]; f[ch[fa][what]]=fa; ch[x][what^1]=fa; f[fa]=x; f[x]=pa; update(fa); update(x); return; } inline void splay(int x) { for(int fa;(fa=f[x]);rotate(x)) if(f[fa]) rotate((get(x)==get(fa)?fa:x)); root=x; return; } inline void insert(int x) { if(!root) { sz++; key[sz]=x; cnt[sz]=size[sz]=1; root=sz; return; } int now=root,fa=0; while(1) { if(key[now]==x) { cnt[now]++; splay(now); return; } fa=now; now=ch[now][key[now]<x]; if(!now) { f[++sz]=fa; key[sz]=x; size[sz]=cnt[sz]=1; ch[fa][key[fa]<x]=sz; splay(sz); return; } } } inline void find(int x) { int now=root; while(1) { if(x<key[now]) { now=ch[now][0]; continue; } if(key[now]==x) { splay(now); return; } now=ch[now][1]; } return; } inline int rank(int x) { find(x); return size[ch[root][0]]+1; } inline int findx(int x) { int now=root; while(1) { if(size[ch[now][0]]>=x) { now=ch[now][0]; continue; } int lon=size[ch[now][0]]+cnt[now]; if(x<=lon) return key[now]; x-=lon; now=ch[now][1]; } } inline void del(int x) { find(x); if(cnt[root]>1){cnt[root]--;return;} if(size[root]==1){clear(root);root=0;return;} if (!ch[root][0]){int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;} if (!ch[root][1]){int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;} int now=ch[root][0],old=root; while(ch[now][1])now=ch[now][1]; f[ch[old][1]]=now; ch[now][1]=ch[old][1]; f[ch[old][0]]=0; clear(old); splay(now); return; } inline int pre(int x) { insert(x); int now=ch[root][0]; while(ch[now][1])now=ch[now][1]; del(x); return key[now]; } inline int next(int x) { insert(x); int now=ch[root][1]; while(ch[now][0])now=ch[now][0]; del(x); return key[now]; } int main() { freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); scanf("%d",&n); while(n--) { int x,y; scanf("%d%d",&y,&x); switch(y) { case 1:insert(x);break; case 2:del(x);break; case 3:printf("%d\n",rank(x));break; case 4:printf("%d\n",findx(x));break; case 5:printf("%d\n",pre(x));break; case 6:printf("%d\n",next(x));break; } } return 0; }
Treap
#include<cstdio> #include<iostream> #include<cstdlib> #define MAXN 100005 using namespace std; int ch[MAXN][2],key[MAXN],r[MAXN],size[MAXN],cnt[MAXN],root,sz,n,m; inline void update(int x) { size[x]=size[ch[x][1]]+size[ch[x][0]]+cnt[x]; } inline void rotate(int &x) { int wh=r[ch[x][1]]>r[ch[x][0]],son=ch[x][wh]; ch[x][wh]=ch[son][wh^1]; ch[son][wh^1]=x; update(x); update(son); x=son; } void insert(int &now,int x) { if(!now) { now=++sz; cnt[sz]=size[sz]=1; key[sz]=x; r[sz]=(rand()%100+rand()); return; } if(key[now]==x) { cnt[now]++; size[now]++; return; } insert(ch[now][key[now]<x],x); if(r[now]<r[ch[now][key[now]<x]]) rotate(now); else update(now); } void del(int &now,int x) { if(key[now]==x) { if(cnt[now]>1) { cnt[now]--; size[now]--; return; } if(ch[now][1]*ch[now][0]==0) { now=ch[now][1]+ch[now][0]; return; } rotate(now); del(ch[now][key[ch[now][1]]==x],x); update(now); return; } del(ch[now][key[now]<x],x); update(now); } inline int kth(int x) { int now=root; while(1) { if(size[ch[now][0]]>=x) { now=ch[now][0]; continue; } int lon=cnt[now]+size[ch[now][0]]; if(lon>=x) return key[now]; x-=lon; now=ch[now][1]; } } inline int rank(int x) { int now=root,ans=0; while(1) { if(key[now]==x) return ans+1+size[ch[now][0]]; if(x<key[now]) { now=ch[now][0]; continue; } ans+=cnt[now]+size[ch[now][0]]; now=ch[now][1]; } } inline int pre(int x) { int now=root,ans=-0x7fffffff; while(now) if(key[now]<x) { if(key[now]>ans) ans=key[now]; now=ch[now][1]; } else now=ch[now][0]; return ans; } inline int next(int x) { int now=root,ans=0x7fffffff; while(now) if(key[now]>x) { if(key[now]<ans) ans=key[now]; now=ch[now][0]; } else now=ch[now][1]; return ans; } int main() { freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); scanf("%d",&n); while(n--) { int x,y; scanf("%d%d",&y,&x); switch(y) { case 1:insert(root,x);break; case 2:del(root,x);break; case 3:printf("%d\n",rank(x));break; case 4:printf("%d\n",kth(x));break; case 5:printf("%d\n",pre(x));break; case 6:printf("%d\n",next(x));break; } } return 0; }
ScapeGoat_Tree
#include<cstdio> #include<iostream> using namespace std; const int MAXN=200010; const double a=0.75; struct node { node *ch[2]; int key,size,cover,ex; inline void update() { size=ch[0]->size+ch[1]->size+ex; cover=ch[0]->cover+ch[1]->cover+1; } inline bool bad() { return ch[0]->cover>=cover*a+5||ch[1]->cover>=cover*a+5; } }Mem[MAXN],*null,*root,*stack[MAXN],*lst[MAXN]; int len,top; inline void Init() { root=null=Mem; null->size=null->cover=null->ex=0; null->ch[0]=null->ch[1]=Mem; for(int i=1;i<MAXN;i++)stack[++top]=Mem+i; } inline node *New(int key) { node *t=stack[top--]; t->ch[0]=t->ch[1]=null; t->size=t->cover=t->ex=1; t->key=key; return t; } inline void travel(node *p) { if(p==null)return; travel(p->ch[0]); if(p->ex)lst[++len]=p; else stack[++top]=p; travel(p->ch[1]); } inline node *divide(int l,int r) { if(l>r)return null; int mid=(l+r)>>1; lst[mid]->ch[0]=divide(l,mid-1); lst[mid]->ch[1]=divide(mid+1,r); lst[mid]->update(); return lst[mid]; } inline void rebuild(node *&p) { len=0; travel(p); p=divide(1,len); } inline node **insert(node *&p,int key) { if(p==null) { p=New(key); return &null; } p->size++; p->cover++; node **ret=insert(p->ch[p->key<=key],key); if(p->bad())ret=&p; return ret; } inline void erace(node *p,int k) { //cout<<p->ch[0]->size<<endl; p->size--; if(p->ex&&k==p->ch[0]->size+1) { p->ex=0; return; } if(k<=p->ch[0]->size)erace(p->ch[0],k); else erace(p->ch[1],k-p->ch[0]->size-p->ex); } inline int Kth(int k) { node *p=root; while(p!=null) { if(p->ex&&k==p->ch[0]->size+1)return p->key; else if(p->ch[0]->size>=k)p=p->ch[0]; else k-=p->ch[0]->size+p->ex,p=p->ch[1]; } } inline int Rank(int x) { node *p=root; int ret=1; while(p!=null) if(p->key>=x) p=p->ch[0]; else ret+=p->ch[0]->size+p->ex,p=p->ch[1]; return ret; } inline void Insert(int x) { node **p=insert(root,x); if(*p!=null)rebuild(*p); } inline void Erace_kth(int k) { erace(root,k); if(root->size<root->cover*a)rebuild(root); } inline void Erace(int x) { Erace_kth(Rank(x)); } int main() { freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); Init(); int Q,opt,x; scanf("%d",&Q); while(Q--) { scanf("%d%d",&opt,&x); switch(opt) { case 1:Insert(x);break; case 2:Erace(x);break; case 3:printf("%d\n",Rank(x));break; case 4:printf("%d\n",Kth(x));break; case 5:printf("%d\n",Kth(Rank(x)-1));break; case 6:printf("%d\n",Kth(Rank(x+1)));break; } } }
以上是关于bzoj3224Tyvj 1728 普通平衡树 平衡树的三种姿势 :splay,Treap,ScapeGoat_Tree的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3224: Tyvj 1728 普通平衡树 treap
BZOJ3224: Tyvj 1728 普通平衡树[treap]