• 【BZOJ3224】【tyvj1728】普通平衡树


    最近开始学习平衡树,在学长的强烈推荐下学习了AVL、红黑树、splay(以上我都还没学)treap。

    首先讲一下个人对treap(树堆)的理解。

    treap,顾名思义,就是tree+heap,首先因为treap是一棵平衡树,因此它满足二叉排序树的性质,接下来,为了防止BST退化成一条链,它使用了随机化的方式给每个点分布一个优先级,然后要求优先级满足堆的性质,但不必是一棵完全二叉树,这样的效率期望就是每次基础操作( log n )的。

    然后简单讲一下树堆的基础操作,代码参见例题与AC代码。

    1.插入     平衡树最基础的操作之一就是插入一个新节点,首先我们按照BST的性质插入这个节点,接下来按照优先级进行旋转维护堆的性质,这样就可以了。

    2.删除   平衡树最基础的操作之二就是删除一个原有节点,同样的我们按照BST的性质找到这个节点,然后按照BST的方法删除它,接下来维护堆的性质即可。

    3.查找     平衡树最基础的操作之三就是查找,一般主要包含2种查找:1)给定一个权值,查找排名 2)给定一个排名,查找权值 这2种操作是大同小异的,都只需要按照BST的性质来进行即可。

    下面是本题题解。

    题目就是平衡树最基础的操作裸题,所以就直接参考上面所说的以及代码就好了。(1912KB 232ms on BZOJ)

    #include <stdio.h>
    #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),S==TT)?EOF:*S++)
    char BB[1<<15],*TT=BB,*S=BB;
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline int rad(){
        static int x=23333;
        x^=x<<13,x^=x>>17,x^=x<<5;return x;
    }
    struct treap{
        treap *ls,*rs;
        int val,pri,cnt,sz;
        treap(int val):val(val){ls=rs=NULL,cnt=sz=1,pri=rad();}
        void combine(){sz=cnt;if (ls!=NULL) sz+=ls->sz;if (rs!=NULL) sz+=rs->sz;}
    }*root;
    inline void lrotate(treap* &x){treap *y=x->rs;x->rs=y->ls;y->ls=x;y->sz=x->sz;x->combine();x=y;}
    inline void rrotate(treap* &x){treap *y=x->ls;x->ls=y->rs;y->rs=x;y->sz=x->sz;x->combine();x=y;}
    inline void Insert(treap* &x,int val){
        if (x==NULL){x=new treap(val); return;}
        if (val==x->val) x->cnt++;
        else if (val>x->val){Insert(x->rs,val);if (x->rs->pri<x->pri) lrotate(x);}
        else {Insert(x->ls,val);if (x->ls->pri<x->pri) rrotate(x);}x->combine();
    }
    void Delete(treap *&x,int val){
        if (x==NULL) return;
        if (val==x->val){
            if (x->cnt>1) x->cnt--,x->sz--;
            else if (x->ls==NULL||x->rs==NULL){
                treap *t=x;
                if (x->ls==NULL) x=x->rs;
                else x=x->ls;
                delete t;
            }
            else if (x->ls->pri<x->rs->pri)
                rrotate(x),Delete(x,val);
            else lrotate(x),Delete(x,val);
        }
        else if (val<x->val) x->sz--,Delete(x->ls,val);
        else x->sz--,Delete(x->rs,val);
    }
    inline int find(treap *x,int val){
        if (x==NULL) return 0;
        if (x->ls==NULL){
            if (val==x->val) return 1;
            if (val>x->val) return find(x->rs,val)+x->cnt;
            return 0;
        }
        if (val==x->val)return x->ls->sz+1;
        if (val<x->val) return find(x->ls,val);
        return find(x->rs,val)+x->ls->sz+x->cnt;
    }
    inline int find_rank(treap *x,int k){
        if (x==NULL) return 0;
        if (x->ls==NULL){
            if (k<=x->cnt) return x->val;
            else return find_rank(x->rs,k-x->cnt);
        }
        if (k<=x->ls->sz) return find_rank(x->ls,k);
        if (k>x->ls->sz+x->cnt) return find_rank(x->rs,k-x->ls->sz-x->cnt);
        return x->val;
    }
    int find_pre(treap *x,int val,int ans){
        if (x==NULL) return ans;
        if (val>x->val) return find_pre(x->rs,val,x->val);
        return find_pre(x->ls,val,ans);
    }
    int find_nxt(treap *x,int val,int ans){
        if (x==NULL) return ans;
        if (val<x->val) return find_nxt(x->ls,val,x->val);
        return find_nxt(x->rs,val,ans);
    }
    int main(){
        int q=read(); 
        while (q--){
            int opt=read(),x=read();
            switch (opt){
                case 1:Insert(root,x); break;
                case 2:Delete(root,x); break;
                case 3:printf("%d
    ",find(root,x)); break;
                case 4:printf("%d
    ",find_rank(root,x)); break;
                case 5:printf("%d
    ",find_pre(root,x,-1)); break;
                case 6:printf("%d
    ",find_nxt(root,x,-1)); break; 
            }
        }
    }
  • 相关阅读:
    Tabindex
    bootStrap下拉菜单 点击下拉列表某个元素,列表不隐藏
    ionic--分模块
    ionic--配置路由
    ionic —指令
    一个简单的Makefile的编写【用自己的话,解释清楚这些】
    使用ptrace向已运行进程中注入.so并执行相关函数
    StrictMode模式介绍
    adb server is out of date. killing...
    交叉编译lsof for android
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ3224.html
Copyright © 2020-2023  润新知