码迷,mamicode.com
首页 > 其他好文 > 详细

fhq treap

时间:2018-06-09 13:10:42      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:中间   html   turn   open   target   span   col   while   memcpy   

最近突然想学平衡树,原先想学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指向上更新
View Code

 

合并:把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的肯定知道)
View Code

 

新建一个节点:

技术分享图片
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指这个节点和它的子树一共有多少节点
View Code

 

接下来是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 }
View Code

 

完整代码:(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(\n);}
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 }
View Code

 

fhq treap

标签:中间   html   turn   open   target   span   col   while   memcpy   

原文地址:https://www.cnblogs.com/mimiorz/p/9158446.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!