fhq treap
Posted mimiorz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fhq treap相关的知识,希望对你有一定的参考价值。
最近突然想学平衡树,原先想学splay,但是splay太难了,代码又长,本蒟蒻不大理解,又听机房的大佬们说有一种神奇的平衡树--fhq发明的fhq treap,能完成splay的所有功能又容易理解,代码短,便兴致勃勃地去学了。
最好先去学treap或了解一下treap,知道一些常识
先推荐两篇blog:
http://www.yhzq-blog.cc/fhq-treap%E6%80%BB%E7%BB%93/
https://www.cnblogs.com/Sakits/p/7906318.html
这篇文章也是参考这两篇blog写的,某些图片、代码、文字也转自这篇blog
在阅读我的文章时,如果中间有不确定的部分,可以先跳到后面的完整代码研究。
fhq treap又称无旋treap,是通过分裂和合并来完成各种插入区间,删除区间,翻转区间等操作的。
我们来讲讲它的两个关键操作:分裂和合并
分裂:把一棵子树分成l,r两棵子树。
把前k个分到左子树,其他分到右子树
如图
转自http://www.yhzq-blog.cc
inline void sl(ll x,ll &l,ll &r,ll k){ if(!k)r=x,l=0; else if(k==tr[x].siz)l=x,r=0; else (k<=tr[lt].siz)?(pd(r=x),sl(lt,l,lt,k)):(pd(l=x),sl(rt,rt,r,k-tr[lt].siz-1)),pu(x); } //lt指左子树,rt指右子树,siz指子树大小,pd指下推,pu指向上更新
合并:把l子树和r子树合并为子树x
如图:
转自http://www.yhzq-blog.cc
1 inline void mg(ll &x,ll l,ll r){ 2 if(!l||!r)x=l+r; 3 else (tr[l].rnd<tr[r].rnd)?(pd(x=l),mg(rt,rt,r)):(pd(x=r),mg(lt,l,lt)),pu(x); 4 } 5 //rnd指一棵子树的随机权值(学过treap的肯定知道)
新建一个节点:
1 inline void bt(ll &x,ll v){ 2 tr[x=++sz].rnd=rand()<<15|rand(); 3 tr[x].s=v;tr[x].siz=1; 4 } 5 //s指节点的值,siz指这个节点和它的子树一共有多少节点
接下来是insert:插入一个值为v的节点
先找v的排名,然后分裂,排在v前面的分在左子树,其他的在右子树,然后在中间插入这个节点,接着把三个部分合并在一起。
1 inline void ins(ll v){ 2 ll x,y,rk=rank(RT,v),nt; 3 sl(RT,x,y,rk);bt(nt,v); 4 mg(x,x,nt);mg(RT,x,y); 5 }
完整代码:(bzoj 3224: Tyvj 1728 普通平衡树)
1 #include<bits/stdc++.h> 2 #define ll int 3 #define max(x,y) ((x)>(y)?(x):(y)) 4 #define min(x,y) ((x)<(y)?(x):(y)) 5 #define fur(i,x,y) for(i=x;i<=y;i++) 6 #define fdr(i,x,y) for(i=x;i>=y;i--) 7 #define Fur(i,x,y) for(ll i=x;i<=y;i++) 8 #define Fdr(i,x,y) for(ll i=x;i>=y;i--) 9 #define in2(x,y) in(x);in(y) 10 #define in3(x,y,z) in2(x,y);in(z) 11 #define in4(a,b,c,d) in2(a,b);in2(c,d) 12 #define clr(x,y) memset(x,y,sizeof(x)) 13 #define cpy(x,y) memcpy(x,y,sizeof(x)) 14 #define fl(i,x) for(ll i=head[x],to;to=e[i].to,i;i=e[i].next) 15 #define inf 233333333 16 using namespace std; 17 /*---------------------------------------*/ 18 #define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0) 19 #define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0) 20 #define gc ((*fib::f)?(*(fib ::f++)):(fgets(fib::b,sizeof(fib::b),stdin)?(fib::f=fib::b,*(fib::f++)):-1)) 21 namespace fib{char b[300000]= {},*f=b;}inline void in(ll &x){x=0;char c;bool f=0;while((c=gc)>‘9‘||c<‘0‘)if(c==‘-‘)f=!f;x=c-48;while((c=gc)<=‘9‘&&c>=‘0‘)x=x*10+c-48;if(f)x=-x;}namespace fob{char b[300000]= {},*f=b,*g=b+300000-2;}struct foce{~foce(){pob;fflush(stdout);}} _foce;namespace ib{char b[100];}inline void out(ll x){if(x==0){pc(48);return;}if(x<0){pc(‘-‘);x=-x;}char *s=ib::b;while(x) *(++s)=x%10,x/=10;while(s!=ib::b) pc((*(s--))+48);}inline void outn(ll x){out(x);pc(‘ ‘);} 22 inline void swap(ll &x,ll &y){ll t=x;x=y;y=t;} 23 inline ll jdz(ll x){return x>=0?x:-x;} 24 /*------------------------------------------------------------------------------------------------*/ 25 #define N 110000 26 #define lt tr[x].ls 27 #define rt tr[x].rs 28 ll n,sz=0,RT; 29 struct fhq{ll siz,s,rnd,ls,rs;}tr[N]; 30 inline void pu(ll x){tr[x].siz=tr[lt].siz+tr[rt].siz+1;} 31 inline void bt(ll &x,ll v){ 32 tr[x=++sz].rnd=rand()<<15|rand(); 33 tr[x].s=v;tr[x].siz=1; 34 } 35 inline void sl(ll x,ll &l,ll &r,ll k){ 36 if(!k)r=x,l=0; 37 else if(k==tr[x].siz)l=x,r=0; 38 else (k<=tr[lt].siz)?(r=x,sl(lt,l,lt,k)):(l=x,sl(rt,rt,r,k-tr[lt].siz-1)),pu(x); 39 } 40 inline void mg(ll &x,ll l,ll r){ 41 if(!l||!r)x=l+r; 42 else (tr[l].rnd<tr[r].rnd)?(x=l,mg(rt,rt,r)):(x=r,mg(lt,l,lt)),pu(x); 43 } 44 inline ll rank(ll x,ll v){ 45 if(!x)return 0; 46 return (tr[x].s>=v)?rank(lt,v):rank(rt,v)+tr[lt].siz+1; 47 } 48 inline void ins(ll v){ 49 ll x,y,rk=rank(RT,v),nt; 50 sl(RT,x,y,rk);bt(nt,v); 51 mg(x,x,nt);mg(RT,x,y); 52 } 53 inline void del(ll v){ 54 ll x,y,z,rk=rank(RT,v)+1; 55 sl(RT,x,y,rk);sl(x,x,z,rk-1); 56 mg(RT,x,y); 57 } 58 inline ll find(ll k){ 59 ll x,y,z,ans; 60 sl(RT,x,y,k);sl(x,z,x,k-1); 61 ans=tr[x].s; 62 mg(x,z,x);mg(RT,x,y); 63 return ans; 64 } 65 inline ll pre(ll v){ 66 ll x,y,z,ans,rk=rank(RT,v); 67 sl(RT,x,y,rk);sl(x,z,x,rk-1); 68 ans=tr[x].s; 69 mg(x,z,x);mg(RT,x,y); 70 return ans; 71 } 72 inline ll nxt(ll v){ 73 ll x,y,z,ans,rk=rank(RT,v+1); 74 sl(RT,x,y,rk+1);sl(x,z,x,rk); 75 ans=tr[x].s; 76 mg(x,z,x);mg(RT,x,y); 77 return ans; 78 } 79 int main(){ 80 ll u,x; 81 srand(19260817); 82 in(n);tr[0].rnd=tr[0].s=inf; 83 while(n--){ 84 in2(u,x); 85 switch(u){ 86 case 1:ins(x);break; 87 case 2:del(x);break; 88 case 3:outn(rank(RT,x)+1);break; 89 case 4:outn(find(x));break; 90 case 5:outn(pre(x));break; 91 case 6:outn(nxt(x));break; 92 } 93 } 94 }
以上是关于fhq treap的主要内容,如果未能解决你的问题,请参考以下文章