平衡树

BST

笛卡尔树

笛卡尔树是一种树形结构,从key来看,它满足二叉搜索树的性质,从value来看,它满足堆的性质。

由数组构建笛卡尔树:
(1)将元素a[0]作为树的根节点
(2)for i in range(1,n)
如果a[i]小于根节点,则将a[i]作为R的父节点
如果a[i]大于根节点R,则从根节点的右子树查找位置


Fhq-Treap

数值操作

模板题-洛谷P3669

#include<bits/stdc++.h>
using namespace std;

namespace ftp {
    const int MAXN=(int)1e6+10;
    struct Node {
        int value,random,size,lson,rson;
    } tree[MAXN];
    #define val(p) tree[p].value
    #define rnd(p) tree[p].random
    #define siz(p) tree[p].size
    #define l(p) tree[p].lson
    #define r(p) tree[p].rson

    int cnt=0,root=0,x=0,y=0,z=0;

    void update(int p)
    {
        siz(p)=siz(l(p))+siz(r(p))+1;
    }

    void split(int p,int k,int &x,int &y)
    {
        if (p==0) {
            x=y=0;
            return;
        }
        if (val(p)<=k) {
            x=p;
            split(r(p),k,r(p),y);
        } else {
            y=p;
            split(l(p),k,x,l(p));
        }
        update(p);
    }

    int merge(int x,int y)
    {
        if (x==0 || y==0) {
            return x+y;
        }
        if (rnd(x)<rnd(y)) {
            r(x)=merge(r(x),y);
            update(x);
            return x;
        } else {
            l(y)=merge(x,l(y));
            update(y);
            return y;
        }
    }

    inline int rand()
    {
        static int seed=19260817;
        return seed=seed*23333LL%0x7fffffff;
    }

    int newNode(int v)
    {
        tree[++cnt]={v,rand(),1,0,0};
        return cnt;
    }

    void ins(int v)
    {
        split(root,v,x,y);
        root=merge(merge(x,newNode(v)),y);
    }

    void del(int v)
    {
        split(root,v,x,z);
        split(x,v-1,x,y);
        y=merge(l(y),r(y));
        root=merge(merge(x,y),z);
    }

    int rnk(int v)
    {
        split(root,v-1,x,y);
        int ans=siz(x)+1;
        root=merge(x,y);
        return ans;
    }

    int kth(int p,int k)
    {
        while (true) {
            if (k<=siz(l(p))) {
                p=l(p);
            } else if (k==siz(l(p))+1) {
                return val(p);
            } else {
                k-=siz(l(p))+1;
                p=r(p);
            }
        }
    }

    int pre(int v)
    {
        split(root,v-1,x,y);
        int ans=kth(x,siz(x));
        root=merge(x,y);
        return ans;
    }

    int suf(int v)
    {
        split(root,v,x,y);
        int ans=kth(y,1);
        root=merge(x,y);
        return ans;
    }
}

int main()
{
    int n;
    cin>>n;
    for (int i=0;i<n;i++) {
        int opt,v;
        scanf("%d%d",&opt,&v);
        switch (opt) {
            case 1:
                ftp::ins(v);
                break;
            case 2:
                ftp::del(v);
                break;
            case 3:
                printf("%d\n",ftp::rnk(v));
                break;
            case 4:
                printf("%d\n",ftp::kth(ftp::root,v));
                break;
            case 5:
                printf("%d\n",ftp::pre(v));
                break;
            case 6:
                printf("%d\n",ftp::suf(v));
                break;
        }
    }
    return 0;
}

区间操作

留下评论