Some time ago to learn fhqtreap ... Today, nothing to summarize a little bit ... After learning FHQ, I never want to write splay again.
the advantages of Fhqtreap : Fast speed, simple code, can be used for interval operation, but also can be persisted.
Learning this first has to understand the balance tree and can be stacked.
The first thing to make clear is that fhqtreap is essentially a treap, which means that it also relies on heap weights to maintain the balance of the tree. But the fhqtreap does not rotate, only two simplest operations split (split) and merge (merge), through these two operations to maintain the nature of the balance tree. We use W to represent weights stored in the balance tree, and F for heap weights.
1.split (ROOT,V,K1,K2)
This operation is to split a root tree into two parts, the weight of less than v placed in a balance tree, greater than w in another balance tree, the last return of the K1,k2 value is the root of the two trees.
Below we consider how to divide. Note that the k1,k2 here are all arguments, K1 represents a tree less than V, and K2 represents a tree greater than V.
If the current node is I, then we compare the size of T[I].W and V, if t[i].w<=v, then we can be sure that the left subtree of I is also less than V, but for the right subtree we are not sure. In this way, make k1=i, and then split (T[I].R,V,T[I].R,K2), equivalent to the right subtree of I cut down, the right sub-tree of I recursively processing I, split the right subtree, but this time the position of K1 has been occupied by I, then if there is less than V, We are directly connected to the right child of I (because it is still in a tree), so as to satisfy the nature of the binary sort tree. At the same time we are from the top of the demolition, splicing, so do not consider F also satisfies the heap nature
If T[i].w>v, in the same vein, K2=i,split (T[I].L,V,K1,T[I].L)
So we call split (ROOT,V,K1,K2), we can split a tree into two, similar to the splay to rotate the demarcation point to the root, so that we can find in the K1 more than W node information, in K2 to find the node less than W information.
2.root=merge (K1,K2)
This operation means to turn the K1,K2 two trees into one and return the number of the root node, noting that all w K1 here is less than K2, because this operation is usually done by split and then processing the information and then back to a tree.
It's a good idea to learn and heap. To determine the size of the two tree, we just need to consider their heap weights. This defaults to the large root heap.
For T[k1].f>t[k2].f,t[k1].r=merge (T[K1].R,K2); return K1;
For T[k1].f<t[k2].f,t[k2].l=merge (K1,T[K2].L); return K2;
Note that we want to ensure that the size of the two subtrees is constant at each recursive processing, so the order should be noted.
So we can do all sorts of things with these two basics.
3.insert (v)
Insert a point with a weight of V, the tree according to the weight of V two, and then merge back in order.
There are also more efficient insertion methods, depending on the code
4.del (v)
Delete the point with a weight of V, divide the tree into two k1,k2 according to V, and divide the K2 into K3,k4,merge (merge (K1,T[K3].L), merge (T[K3].R,K4) according to V+1
5. Subsequent search
Split (ROOT,V,K1,K2), find the maximum minimum value in K1,k2, respectively
6. Query ranking
Split (ROOT,V,K1,K2), ranking is K1 size
7. Interval operation
Splite (ROOT,L-1,K1,K2); Splite (K2,R,K3,K4); K3 is the operating interval.
Here is the classic normal balance tree template, a little bit different is that I put weights and values equal to the second tree in the
1/**************************************************************2Problem:32243User:10909007154 language:pascal5 result:accepted6Time: -Ms7Memory:2180KB8****************************************************************/9 Ten Programj01; One typexx=RecordL,r,f,w,size:longint;End; A varT:Array[0..100086] ofxx; - N,i,op,x,k1,k2,k3,k4,root,tt:longint; - the procedureUpdate (i:longint); - begin - ifI=0 Thenexit; -T[i].size:=t[t[i].l].size+t[t[i].r].size+1; + End; - + functionmerge (X,y:longint): Longint; A begin at if(x=0)or(y=0) ThenExit (x+y); - ifT[x].f>t[y].f Then - begin -t[x].r:=merge (t[x].r,y); - update (x); exit (x) ; - End Else in begin -t[y].l:=merge (X,T[Y].L); to update (y); exit (y) ; + End; - End; the * procedureSplite (I,x:longint;vark1,k2:longint); $ beginPanax Notoginseng ifI=0 Then - begin thek1:=0; k2:=0; exit; + End; A ifT[i].w<x Then the begin +k1:=I;splite (T[I].R,X,T[I].R,K2); - End Else $ begin $k2:=I;splite (T[I].L,X,K1,T[I].L); - End; - update (i); the End; - Wuyi functionInsert (i,k:longint): Longint; the begin - ifI=0 Thenexit (k); Wu ifT[i].f>t[k].f Then - begin About ifT[i].w<t[k].w Thent[i].r:=Insert (t[i].r,k) $ Elset[i].l:=Insert (t[i].l,k); - update (i); exit (i); - End; - Splite (I,T[K].W,T[K].L,T[K].R); update (k); exit (k) ; A End; + the functionFind (I,x:longint): Longint; - begin $ ifT[t[i].l].size+1=x Thenexit (T[I].W); the ifT[t[i].l].size>=x Thenexit (Find (t[i].l,x)) the ElseExit (Find (t[i].r,x-t[t[i].l].size-1)); the End; the - functionFindpre (i:longint): Longint; in begin the whileT[i].r<>0 Doi:=T[i].r;exit (T[I].W); the End; About the functionFindnex (i:longint): Longint; the begin the whileT[i].l<>0 Doi:=T[i].l;exit (T[I].W); + End; - the beginBayiREADLN (n); tt:=0; root:=0; the Randomize; the fori:=1 toN Do - begin - readln (op,x); the ifop=1 Then the begin the Inc (TT); theT[tt].w:=x;t[tt].f:=random (maxlongint); t[tt].size:=1; -root:=Insert (ROOT,TT); the End; the ifop=2 Then the begin94Splite (ROOT,X,K1,K2); Splite (k2,x+1, K2,K3); theroot:=Merge (merge ( k1,t[k2].l), merge (T[K2].R,K3)); the End; the ifop=3 Then98 begin AboutSplite (ROOT,X,K1,K2); Writeln (t[k1].size+1); -root:=merge (K1,K2);101 End;102 ifop=4 ThenWriteln (Find (root,x));103 ifop=5 Then104 begin the Splite (ROOT,X,K1,K2); Writeln (Findpre (K1));106root:=merge (K1,K2);107 End;108 ifop=6 Then109 begin theSplite (root,x+1, K1,K2);111 Writeln (Findnex (K2)); theroot:=merge (K1,K2);113 End; the End; the End.
Fhqtreap's study notes