Luo Gu P3369 [template] general balanced tree treap

URL: https://www.luogu.org/problem/P3369

Meaning of the questions:

Preparation of a data structure in each $ O (logn) (1 \ leq n \ leq 1e6) $ following functions:

A, is inserted into a sequence number; two, delete a number in the sequence; Third, find the large $ k $; Fourth, a large number of interrogation $ $ K; V, X $ $ find precursors, six, find $ x $ successor.

answer:

Obviously, the binary search tree can accomplish this task, but in the worst case, a binary tree would degenerate into a chain, it will time out, so we need a balanced binary tree, which is more easy to write, fast speed is treap. treap divided into non-spin and spin treap treap, the former is faster, but does not support persistence, which is slow, but persistent support.

First, there are spin treap

Treap right node maintains a value of a binary nature, in order to balance, it is necessary that it is balanced by a number of additional properties to maintain the stack, this number is a random number corresponding to each node. When rotating in the rotation random number, divided into left and right hand, as shown:

(Reference blog: https://blog.csdn.net/K346K346/article/details/50808879 )

Left and right hand

Obviously the right subtree, right-handed child is left of the original tree roots become root, and the root of the left subtree of the original into the original root of the left subtree, L empathy. After rotating binary tree is easy to prove the nature of change.

When inserted, first find the insertion point, and then rotated back.

More complex remove, delete, delete points to find and select a random value observed subtree as the root of a subtree after the deletion, and then by rotation of the node to be deleted after the move to remove the leaves.

Query operation easy to understand, to see the code.

AC Code:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=100005;
const int inf=0x3f3f3f3f;
struct Treap
{
    struct node
    {
        int val, rnd, lc, rc, size, num;
    };
    int cnt=0;
    node tr[MAXN];
    void init()
    {
        cnt=0;
    }
    int _rand()
    {
        static int seed=12345;
        return seed=(int)seed*482711LL%2147483647; 
    }
    void pushup(int p)
    {
        tr[p].size=tr[tr[p].lc].size+tr[tr[p].rc].size+tr[p].num;
    }
    void right(int &k)
    {
        int tmp=tr[k].lc;
        tr[k].lc=tr[tmp].rc;
        tr[tmp].rc=k;
        tr[tmp].size=tr[k].size;
        pushup(k);
        k=tmp;
    }
    void left(int &k)
    {
        int tmp=tr[k].rc;
        tr[k].rc=tr[tmp].lc;
        tr[tmp].lc=k;
        tr[tmp].size=tr[k].size;
        pushup(k);
        k=tmp;
    }
    void insert(int &p,int x)
    {
        if(p==0)
        {
            p=++cnt;
            tr[p].val=x;
            tr[p].num=tr[p].size=1;
            tr[p].lc=tr[p].rc=0;
            tr[p].rnd=_rand();
            return;
        }
        ++tr[p].size;
        if(x==tr[p].val)
            ++tr[p].num;
        else if(x<tr[p].val)
        {
            insert(tr[p].lc,x);
            if(tr[tr[p].lc].rnd<tr[p].rnd)
                right(p);
        }
        else if(x>tr[p].val)
        {
            insert(tr[p].rc,x);
            if(tr[tr[p].rc].rnd<tr[p].rnd)
                left(p);
        }
    }
    void del(int &p,int x)
    {
        if(p==0)
            return;
        if(tr[p].val==x)
        {
            if(tr[p].num>1)
                --tr[p].num,--tr[p].size;
            else
            {
                if(tr[p].lc==0||tr[p].rc==0)
                    p=tr[p].lc+tr[p].rc;
                else if(tr[tr[p].lc].rnd<tr[tr[p].rc].rnd)
                    right(p),del(p,x);
                else if(tr[tr[p].lc].rnd>tr[tr[p].rc].rnd)
                    left(p),del(p,x);
            }
        }
        else if(tr[p].val<x)
            --tr[p].size,del(tr[p].rc,x);
        else
            --tr[p].size,del(tr[p].lc,x);
    }
    int queryrnk(int &p,int x)
    {
        if(p==0)
            return 0;
        else if(tr[p].val==x)
            return tr[tr[p].lc].size+1;
        else if(tr[p].val<x)
            return tr[tr[p].lc].size+tr[p].num+queryrnk(tr[p].rc,x);
        else 
            return queryrnk(tr[p].lc,x);
    }
    int querynum(int &p,int rnk)
    {
        if(p==0)
            return 0;
        if(tr[tr[p].lc].size>=rnk)
            return querynum(tr[p].lc,rnk);
        rnk-=tr[tr[p].lc].size;
        if(rnk<=tr[p].num)
            return tr[p].val;
        rnk-=tr[p].num;  
        return querynum(tr[p].rc,rnk);
    }
    int queryfront(int &p,int x)
    {
        if(p==0)
            return -inf;
        if(tr[p].val<x)
            return max(tr[p].val,queryfront(tr[p].rc,x));
        else if(tr[p].val>=x)
            return queryfront(tr[p].lc,x);
    }
    int queryback(int &p,int x)
    {
        if(p==0)
            return inf;
        if(tr[p].val>x)
            return min(tr[p].val,queryback(tr[p].lc,x));
        else if(tr[p].val<=x)
            return queryback(tr[p].rc,x);
    }
};
int pos;
Treap tr;
int main()
{
    int n;
    scanf("%d",&n);
    int m,k;
    tr.init();
    for(int i=0;i<n;++i)
    {
        scanf("%d%d",&m,&k);
        if(m==1)
            tr.insert(pos,k);
        else if(m==2)
            tr.del(pos,k);
        else if(m==3)
            printf("%d\n",tr.queryrnk(pos,k));
        else if(m==4)
            printf("%d\n",tr.querynum(pos,k));
        else if(m==5)
            printf("%d\n",tr.queryfront(pos,k));
        else if(m==6)
            printf("%d\n",tr.queryback(pos,k));
    }
    return 0;
}

  

 

 

 

Guess you like

Origin www.cnblogs.com/Aya-Uchida/p/11361489.html