1. 程式人生 > >fhq treap

fhq treap

width OS hide itl 刪除 rand cli 區間 fine

最近突然想學平衡樹,原先想學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