首页 > 其他分享 >『学习笔记』fhq-treap

『学习笔记』fhq-treap

时间:2023-07-29 11:22:30浏览次数:47  
标签:rnk return int 笔记 treap ans mathrm fhq BST

啥是平衡树

这边建议去这里

分裂

一般指的是按值分裂,意思就是以树上的BST(二叉搜索树)的值为关键值分裂。一般会给一个关键值 \(val\) ,把一棵平衡树分裂成BST值 \(\leq val\) 和 \(> val\) 的两部分。

主要思想

从根开始递归,递归到某一节点,如果当前根节点的BST值小于等于你给的那个关键值,就往右子树递归,并且把刚才的根连到左子树根上;否则就往左子树递归,并且把刚才的根连到右子树根上。往哪边递归BST值相对大小关系决定的,而BST值又是由BST本身的性质决定的。

如果递归到叶子结点,需要把左右子树的根都清零!

代码实现

void split(int p, int v, int& x, int& y) {
    if (!p) {
        x = y = 0;
        return;
    }

    if (val[p] <= v) {
        x = p;
        split(r[p], v, r[p], y);
        pushup(x); // fen bie geng xin liang ke zi shu de da xiao
    }

    else {
        y = p;
        split(l[p], v, x, l[p]);
        pushup(y);
    }
}

合并

一般只针对把两个分裂的平衡树(原来这两个平衡树是一个平衡树)合并到一个平衡树里(可以认为是分裂的逆操作)。因为是从一个平衡树分裂来的,所以它们谁是左子树谁是右子树就已经确定了,我们合并的时候就不用管谁左谁右,直接管谁上谁下即可。

主要思想

对于两个分裂的平衡树,我们从上往下递归地比较两个子树的根的heap值(就是随机值)的大小,谁小谁在上(默认小根堆),如果是左边的小,那就递归比较左根的右儿子和右根,否则递归比较左根和右根的左儿子。

如果一个非空根和另一个空根比较,直接返回那个非空根即可。

代码实现

// zhe wan yi zhang de gen xian duan shu he bing you dian xiang
int merge(int x, int y) { // 'x' zuo zi shu gen, 'y' you zi shu gen
    if (!x || !y) return x | y;

    if (rnk[x] < rnk[y]) {
        r[x] = merge(r[x], y);
        pushup(x);
        return x; // bie wang le fan hui
    }

    else {
        l[y] = merge(x, l[y]);
        pushup(y);
        return y;
    }
}

插入一个BST值为 \(v\) 的点

主要思想

先把这个BST值为 \(v\) 点单独开出来作为一个新的平衡树,记为 \(\mathrm{z}\) ;然后再把现有的平衡树按照关键值 \(v\) 分裂为两个平衡树,分别记作 \(\mathrm{x}\) 和 \(\mathrm{y}\) 。先合并 \(\mathrm{x}\) 和 \(\mathrm{z}\) ,再合并 \(\mathrm{y}\) ,就能把这个点插进去。

不用担心如何有没有比较BST值相同但是heap值不同的两个点的heap值,因为它们在合并的时候就已经比较了。

如果插入的是一个序列,那么就先build一下,再合并即可。

代码实现

void Newnode(int& x, int v) {
    x = ++tot;
    val[x] = v;
    rnk[x] = rand();
    siz[x] = 1;
}

void insert(int v) {
    int x, y, z;
    split(root, v, x, y);
    Newnode(z, v);
    root = merge(merge(x, z), y);
}

删除一个BST值为 \(v\) 的点

主要思想

把一棵平衡树分裂成BST值为 \([1, v - 1]\) 、 \(v\) 和 \([v + 1, max]\) 三部分,显然,BST值为 \(v\) 的平衡树是一条链,我们删去这条链的一个点,再把这三部分重新合并即可。

若我们记这条BST值大小为 \(v\) 的链(平衡树)为 \(\mathrm{y}\) ,则我们有操作:$$\mathrm{y} = merge(l[\mathrm{y}], r[\mathrm{y}])$$

这个平衡树不仅是链,而且还是一条向左的链,\(l[\mathrm{y}]\) 可能非空也可能空,\(r[\mathrm{y}]\) 一定空。所以将这两部分合并就相当于抛弃了根节点 \(\mathrm{y}\)。

代码实现

void Delete(int v) {
    int x, y, z, tmp;
    Split(root, v, tmp, z);
    Split(tmp, v - 1, x, y);
    y = Merge(l[y], r[y]);
    root = Merge(Merge(x, y), z);
}

已知权值 \(v\) 查排名 \(rnk\)

主要思想

把平衡树按 \(v - 1\) 分裂,记权值为 \([1, v - 1]\) 的为 \(\mathrm{x}\) , \([v, max]\) 的为 \(\mathrm{y}\) 。即可得:$$rnk = siz[\mathrm{x}] + 1$$

代码实现

int getRankbyVal(int v) {
    int x, y, ans;
    Split(root, v - 1, x, y);
    ans = siz[x];
    root = Merge(x, y);
    return ans;
}

已知排名查权值

主要思想

递归查找,如果左子树大小 \(+ 1\) 等于要查的排名,就直接返回根的权值。否则就递归查找,找哪边比较一下就行了。

代码实现

int getValbyRank(int p, int rnk) {
    if (rnk == siz[l[p]] + 1) return val[p];

    else if (rnk <= siz[l[p]]) {
        return getValbyRank(l[p], rnk);
    }

    else {
        return getValbyRank(r[p], rnk - siz[l[p]] - 1);
    }
}

查 \(v\) 的前驱和后继

懒得打字了,直接粘我代码了。

代码实现

int getPre(int p, int v) {
    int x, y, ans;
    Split(p, v - 1, x, y);
    ans = getValbyRank(x, siz[x]);
    Merge(x, y);
    return ans;
}

int getNxt(int p, int v) {
    int x, y, ans;
    Split(p, v, x, y);
    ans = getValbyRank(y, 1);
    Merge(x, y);
    return ans;
}

总结

有啥好总结的,从前往后学明白了就啥都懂了,根本不用总结,然后就剩多打题了。

把我非常非常烂的板子粘上:

namespace FHQ_TREAP {
    const int maxn = 1000005;
    int l[maxn], r[maxn];
    int val[maxn], rnk[maxn];
    int siz[maxn];
    int tot = 0, root = 0;

    class fhq_Treap {

    public:
        void Pushup(int p) {
            siz[p] = siz[l[p]] + siz[r[p]] + 1; // bie wang le jia 1, yin wei hai you 'p' zi ji ben shen
        }

        void Split(int p, int v, int& x, int& y) {
            if (!p) {
                x = y = 0;
                return;
            }

            if (val[p] <= v) {
                x = p;
                Split(r[p], v, r[p], y);
                Pushup(x); // fen bie geng xin liang ke zi shu de da xiao
            }

            else {
                y = p;
                Split(l[p], v, x, l[p]);
                Pushup(y);
            }
        }

        // zhe wan yi zhang de gen xian duan shu he bing you dian xiang
        int Merge(int x, int y) { // 'x' zuo zi shu gen, 'y' you zi shu gen
            if (!x || !y) return x | y;
            
            if (rnk[x] < rnk[y]) {
                r[x] = Merge(r[x], y);
                Pushup(x);
                return x; // bie wang le fan hui
            }

            else {
                l[y] = Merge(x, l[y]);
                Pushup(y);
                return y;
            }
        }

        void Newnode(int& x, int v) {
            x = ++tot;
            val[x] = v;
            rnk[x] = rand();
            siz[x] = 1;
        }

        void Insert(int p, int v) {
            int x, y, z;
            Split(p, v, x, y);
            Newnode(z, v);
            p = Merge(Merge(x, z), y);
        }

        void Delete(int p, int v) {
            int x, y, z, tmp;
            Split(p, v, tmp, z);
            Split(tmp, v - 1, x, y);
            y = Merge(l[y], r[y]);
            p = Merge(Merge(x, y), z);
        }

        int getRankbyVal(int p, int v) {
            int x, y, ans;
            Split(p, v - 1, x, y);
            ans = siz[x];
            p = Merge(x, y);
            return ans;
        }

        int getValbyRank(int p, int rnk) {
            if (rnk == siz[l[p]] + 1) return val[p];

            else if (rnk <= siz[l[p]]) {
                return getValbyRank(l[p], rnk);
            }

            else {
                return getValbyRank(r[p], rnk - siz[l[p]] - 1);
            }
        }

        int getPre(int p, int v) {
            int x, y, ans;
            Split(p, v - 1, x, y);
            ans = getValbyRank(x, siz[x]);
            Merge(x, y);
            return ans;
        }

        int getNxt(int p, int v) {
            int x, y, ans;
            Split(p, v, x, y);
            ans = getValbyRank(y, 1);
            Merge(x, y);
            return ans;
        }
    };
}

\

\[\huge \mathscr{The\ End.} \]

标签:rnk,return,int,笔记,treap,ans,mathrm,fhq,BST
From: https://www.cnblogs.com/Chronologika/p/17589517.html

相关文章

  • 【笔记】构造题
    听说多做构造题长脑子,至少能让我从机械性的考试里清醒一点吧递归子问题剔除问题边缘例题......
  • [odoo开发笔记05]odoo 15&16 Tree/看板视图添加按钮
    odoo在15及之后版本产生js引用变更,导致14及之前列表视图(Tree/List)添加自定义按钮的方式产生了变化。目前15/16版本列表视图添加按钮有三种方式1.每个明细行上都显示按钮此种Tree视图添加按钮仅需要定位第一个字段,添加button即可创建xml文件(例如sale_view.xml)写入以下内容<?......
  • docker aspnetcore学习笔记
    在终端窗口cmd:  示例应用程序对于示例应用程序,让我们使用.NET从模板创建一个简单的应用程序。在本地计算机中创建一个名为的目录。打开终端并切换到该目录。运行以下命令,使用ASP.NET核心Web应用模板创建C#应用。$mkdirdotnet-docker$cddotnet-docker$dotne......
  • 北大AI公开课13讲全链接+最强干货盘点:视频+笔记+文字实录
    视频地址:北大AI公开课专栏笔记:北大AI公开课刚刚结束的北大AI公开课,由北大人工智能创新中心主任雷鸣组织,以把听者培养为“懂产业的AI人才”为主旨,邀请了13位顶级人工智能产业专家,分别从智能驾驶、智能医疗、智能金融、智能家居、硬件等10多个AI+行业,向学生和从业者全面介绍了......
  • RHCE7 认证之学习笔记
    -------------------------------------------------------------------------------------------初始化:两台服务器设置yum源-------------------------------------------------------------------------------------------[root@system1~]#vim/etc/yum.repos.d/yum.repo[root@......
  • Shiro-使用笔记
    目录零、资料一、使用1.1、环境搭建1.1.1、创建数据库1.1.2、导入依赖1.1.3、编写springboot配置文件1.1.4、创建统一结果集类+pojo+DTO1.1.5、mapper接口及xml1.1.6、service接口及实现类1.1.7、shiro操作数据库的类1.1.8、shiro的配置类1.1.9、统一异常处理1.1.10、control......
  • 【算法】哈希学习笔记
    1.哈希(hash)简介1.1前言又来写算法总结了qwq。今天是2023/7/8,期末考试已经考完了。初二下注定是一个煎熬的学期,所以我在这一学期并没有学什么新算法,OI也没什么长进。但倒是深造了几个算法,比如:dp,hash,线段树。之前一直想写一篇hash的学习笔记,但由于种种原因,并没有写成。于......
  • EPLAN电气绘图笔记
    EPLAN的背景由来发展意义使用软件的一些思维上规则的东西。引入一些新的概念性名词术语及区分介绍。如何完成项目式交付初级标准电气图纸。如何高效简化。   未完待续。。。 ......
  • 春秋战国笔记
    鲁  臧文仲 臧宣叔 臧石齐 高无  颜庚 -颜晋2  相.田常 田盘 田布 公孙会 田和  齐康公 田无宇..田乞2栾氏 高氏 鲍氏灵公..庄公   崔杼景公  庆封  晏子 悼公 国夏 高张 田乞.相简公 平公 田悼子5 田白4 田常.3田盘2田乞1 康公 田和.齐太公.......
  • 小米笔记本pro频繁蓝屏故障解决
    问题描述公司有两台小米pro,之前有同事也遇到过这个问题,一般是用了两年左右出现,刚开始频率还不是很高,大概就3,5天会出现一次,后来基本每天要蓝个两三次,而且每次重启恢复的时间跟次数还有延长的迹象。难点蓝屏的终止代码不同,网上搜不到什么好的解决方案,打电话给小米客服让重装系统,依旧......