Balanced Tree Treap [Simple Introduction]

Balanced tree

First, let's briefly introduce the balanced tree. The balanced tree is a binary search tree, but because the binary search tree sometimes becomes a chain, the complexity cannot be optimized.

The balanced tree uses rotation to rotate the binary search tree into balance, so that the tree can be kept as a full binary tree as much as possible. This complexity is constant. O ( n l O g 2 n )

Treap

Now let me talk about Treap, Treap=Tree+Heap, which is the source of its name, that is, the tree must satisfy the properties of the heap, the left son must be larger than the parent node, and the right son must be larger than the parent node.

But this is obviously contradictory, so we have to open another array and take a random value to satisfy the properties of Heap.

Therefore, the complexity of Treap is very metaphysical. If you are unlucky, it will degenerate into a chain, but the probability is too small, so even if it is impossible, the theoretical estimate is O ( n l O g 2 n )

Let's look at an example first, so that it is convenient to explain BZOJ 3224

Description

You need to write a data structure (refer to the title of the topic) to maintain some numbers, which needs to provide the following operations:

  1. insert x number
  2. Delete the x number (if there are multiple identical numbers, because only one is deleted)
  3. Query the ranking of x number (if there are multiple identical numbers, the smallest ranking is output)
  4. Query for a number with a rank of x
  5. Find the predecessor of x (the predecessor is defined as the largest number less than x)
  6. Find the successor of x (the successor is defined as the smallest number greater than x)

Input

The first line is n, which represents the number of operations. The following n lines each have two numbers opt and x, and opt represents the sequence number of the operation (1<=opt<=6)

Output

For operations 3, 4, 5, and 6, each line outputs a number, indicating the corresponding answer

Sample Input

10

1 106465

4 1

1 317721

1 460929

1 644985

1 84185

1 89851

6 81968

1 492737

5 493598

Sample Output

106465

84185

492737

HINT

1. The data range of n: n<=100000

2. The data range of each number: [-2e9,2e9]

This is a board question for a balanced tree. Let’s first introduce variables .

struct xcw{
    int Son[2],tot,x,Num;
    int &operator [](const int b){return Son[b];}
//  void clean(){Son[0]=Son[1]=tot=x=Num=0;}
}Tre[100005];

tot: The number of nodes in this subtree.

Son[2]: For the left and right nodes, I used overloaded operators , which I think is more convenient.

x: represents the weight of this node, that is, the value that satisfies the binary search tree.

Num: This variable stores random numbers, in order to satisfy the properties of Heap.

The code below is the rotation

int Turn(int &x,int p){int t=Tre[x][p];Tre[x][p]=Tre[t][!p];Tre[t][!p]=x;Change(x);Change(t);x=t;}

Isn't it very convenient to directly combine left-hand and right-hand rotation.

Change() is to correct the number of nodes

void Change(int x){Tre[x].tot=Tre[Tre[x][0]].tot+Tre[Tre[x][1]].tot+1;}

There is also a very important Random() . Because C++ calls rand() too slowly, so I wrote one by hand.

int Random(){
    static int seed=703; //seed可以随便取
    return seed=int(seed*48271LL%2147483647);
}

Then there is the insertion , which is actually the same as the binary search tree, but with a rotation.

void Insert(int &x,int p){
    if(!x){x=++Top;Tre[Top].tot=1;Tre[Top].x=p;Tre[Top].Num=Random();return;}
    Tre[x].tot++;
    if(p<=Tre[x].x){Insert(Tre[x][0],p);if(Tre[Tre[x][0]].Num<Tre[x].Num) Turn(x,0);}
    else{Insert(Tre[x][1],p);if(Tre[Tre[x][1]].Num<Tre[x].Num) Turn(x,1);}
}
if(Tre[Tre[x][0]].Num<Tre[x].Num) Turn(x,0);
if(Tre[Tre[x][1]].Num<Tre[x].Num) Turn(x,1);

This is to satisfy the nature of the heap, and rotate according to this.

Below is delete , rotate the node to be deleted to the leaf, then delete.

void Del(int &x,int p){
    if(Tre[x].x==p){
        if(Tre[x][0]*Tre[x][1]==0){x=Tre[x][0]+Tre[x][1];return;}
        if(Tre[Tre[x][0]].Num<Tre[Tre[x][1]].Num){Turn(x,0);Del(Tre[x][1],p);}
        else{Turn(x,1);Del(Tre[x][0],p);}
    }else if(Tre[x].x>p) Del(Tre[x][0],p);else Del(Tre[x][1],p);
    Change(x);
}

Next is to find

int Fnd(int x,int p){//查找p数的排名 
    if(!x) return 1;
    if(Tre[x].x>=p) return Fnd(Tre[x][0],p);
    else return Fnd(Tre[x][1],p)+Tre[Tre[x][0]].tot+1;
}
int Ask(int x,int p){//查找排名为p的数 
    if(Tre[Tre[x][0]].tot==p-1) return Tre[x].x;
    if(Tre[Tre[x][0]].tot>=p) return Ask(Tre[x][0],p);
    else return Ask(Tre[x][1],p-Tre[Tre[x][0]].tot-1);//在右子树内的排名要减去左子树的个数,应该好理解。
}
int FndMax(int x,int p){//找前驱
    if(!x) return -(1e9);
    if(Tre[x].x<p) return max(Tre[x].x,FndMax(Tre[x][1],p));
    else return FndMax(Tre[x][0],p);
}
int FndMin(int x,int p){//找后继 
    if(!x) return 1e9;
    if(Tre[x].x>p) return min(Tre[x].x,FndMin(Tre[x][0],p));
    else return FndMin(Tre[x][1],p);
}

Treap is finished, it is very simple, it is completely a binary search tree.

See my blog for the complete code

Here are some suggested examples:

BZOJ 1208, BZOJ 1503, BZOJ 1588。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325601102&siteId=291194637