题目传送门

标题说平衡树,那么应该AVL,红黑树都能过,但是这次做这题主要是学习Treap,所以花了几天搞出了这题。其他方法以后再说吧

  • Treap(带旋转)

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = ;
    const int INF = 0x3f3f3f3f;
    struct Treap {
    int son[];
    int val, rand;
    int cnt, size;
    } node[MAXN];
    int root, tot;
    void update(int i) {
    int ls = node[i].son[];
    int rs = node[i].son[];
    node[i].size = node[ls].size + node[rs].size + node[i].cnt;
    }
    void rotate(int& r, int index) {
    int k = node[r].son[index ^ ];
    node[r].son[index ^ ] = node[k].son[index];
    node[k].son[index] = r;
    update(r); update(k);
    r = k;
    }
    void insert(int& r, int v) {
    if (r == ) {
    r = ++ tot;
    node[r].val = v;
    node[r].rand = rand();
    node[r].size = node[r].cnt = ;
    return;
    }
    if (node[r].val == v) {
    node[r].size ++;
    node[r].cnt ++;
    return;
    }
    int index = v > node[r].val;
    insert(node[r].son[index], v);
    if (node[node[r].son[index]].rand < node[r].rand) rotate(r, index ^ );
    update(r);
    }
    void erase(int& r, int v) {
    if (r == ) return;
    if (v == node[r].val) {
    if (node[r].cnt > ) {
    node[r].cnt --;
    node[r].size --;
    return;
    }
    if (node[r].son[] == || node[r].son[] == ) {
    r = node[r].son[] + node[r].son[];
    } else {
    int ls = node[r].son[];
    int rs = node[r].son[];
    int index = node[ls].rand < node[rs].rand;
    rotate(r, index);
    erase(node[r].son[index], v);
    }
    } else {
    int index = v > node[r].val;
    erase(node[r].son[index], v);
    }
    update(r);
    }
    int get_rank(int r, int v) {
    int size = node[node[r].son[]].size;
    int cnt = node[r].cnt;
    if (node[r].val == v) return size + ;
    if (node[r].val > v) return get_rank(node[r].son[], v);
    if (node[r].val < v) return size + cnt + get_rank(node[r].son[], v);
    }
    int get_val(int r, int rk) {
    int size = node[node[r].son[]].size;
    int cnt = node[r].cnt;
    if (rk < size + ) return get_val(node[r].son[], rk);
    if (rk >= size + && rk <= size + cnt) return node[r].val;
    if (rk > size + cnt) return get_val(node[r].son[], rk - size - cnt);
    }
    int get_pre(int r, int v) {
    if (r == ) return -INF;
    if (node[r].val >= v) return get_pre(node[r].son[], v);
    else return max(node[r].val, get_pre(node[r].son[], v));
    }
    int get_suc(int r, int v) {
    if (r == ) return INF;
    if (node[r].val <= v) return get_suc(node[r].son[], v);
    else return min(node[r].val, get_suc(node[r].son[], v));
    }
    int main() {
    srand(time(NULL));
    int n; scanf("%d", &n);
    for (int i = ; i <= n; i++) {
    int opt, x;
    scanf("%d%d", &opt, &x);
    if (opt == ) insert(root, x);
    if (opt == ) erase(root, x);
    if (opt == ) printf("%d\n", get_rank(root, x));
    if (opt == ) printf("%d\n", get_val(root, x));
    if (opt == ) printf("%d\n", get_pre(root, x));
    if (opt == ) printf("%d\n", get_suc(root, x));
    }
    return ;
    }

    学到的第二个用随机数的算法,所以这个Treap的高度也是有的随机的。但是起码不太可能退化成链状。

  • Treap(无旋转)
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = ;
    const int INF = 0x3f3f3f3f;
    struct Treap {
    int ls, rs;
    int val, rand;
    int size;
    } node[MAXN];
    int tot, root;
    int add_node(int v) {
    int i = ++tot;
    node[i].val = v;
    node[i].rand = rand();
    node[i].ls = node[i].rs = ;
    node[i].size = ;
    return i;
    }
    void split(int rt, int& a, int& b, int v) {
    if (rt == ) {
    a = b = ;
    return;
    }
    if (node[rt].val <= v) {
    a = rt;
    split(node[rt].rs, node[a].rs, b, v);
    } else {
    b = rt;
    split(node[rt].ls, a, node[b].ls, v);
    }
    node[rt].size = node[node[rt].ls].size + node[node[rt].rs].size + ;
    }
    void merge(int& rt, int a, int b) {
    if (a == || b == ) {
    rt = a + b;
    return;
    }
    if (node[a].rand < node[b].rand) {
    rt = a;
    merge(node[rt].rs, node[a].rs, b);
    } else {
    rt = b;
    merge(node[rt].ls, a, node[b].ls);
    }
    node[rt].size = node[node[rt].ls].size + node[node[rt].rs].size + ;
    }
    void insert(int& rt, int v) {
    int x = , y = ;
    split(rt, x, y, v);
    merge(x, x, add_node(v));
    merge(rt, x, y);
    }
    void erase(int&rt, int v) {
    int x = , y = , z = ;
    split(rt, x, z, v);
    split(x, x, y, v - );
    merge(y, node[y].ls, node[y].rs);
    merge(x, x, y);
    merge(rt, x, z);
    }
    int get_rank(int rt, int v) {
    int x = , y = ;
    split(rt, x, y, v - );
    int rk = node[x].size + ;
    merge(rt, x, y);
    return rk;
    }
    int get_val(int rt, int rk) {
    int size = node[node[rt].ls].size;
    if (rk < size + ) return get_val(node[rt].ls, rk);
    if (rk == size + ) return node[rt].val;
    if (rk > size + ) return get_val(node[rt].rs, rk - size - );
    }
    int get_pre(int rt, int v) {
    int x = , y = ;
    split(rt, x, y, v - );
    int pre = get_val(x, node[x].size);
    merge(rt, x, y);
    return pre;
    }
    int get_suc(int rt, int v) {
    int x = , y = ;
    split(rt, x, y, v);
    int suc = get_val(y, );
    merge(rt, x, y);
    return suc;
    }
    int main() {
    srand(time(NULL));
    int n; scanf("%d", &n);
    for (int i = ; i <= n; i++) {
    int opt, x;
    scanf("%d%d", &opt, &x);
    if (opt == ) insert(root, x);
    if (opt == ) erase(root, x);
    if (opt == ) printf("%d\n", get_rank(root, x));
    if (opt == ) printf("%d\n", get_val(root, x));
    if (opt == ) printf("%d\n", get_pre(root, x));
    if (opt == ) printf("%d\n", get_suc(root, x));
    }
    return ;
    }

    昨天看懂了带旋转的Treap,今天来写无旋转的Treap,感觉确实是比带旋转的好敲而且好懂,关键就是理解split()和merge()两个核心函数。

洛谷-P3369-普通平衡树(Treap)的更多相关文章

  1. [洛谷P3369] 普通平衡树 Treap & Splay

    这个就是存一下板子...... 题目传送门 Treap的实现应该是比较正经的. 插入删除前驱后继排名什么的都是平衡树的基本操作. #include<cstdio> #include< ...

  2. 洛谷P3369普通平衡树(Treap)

    题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...

  3. 洛谷P3369 普通平衡树

    刚学平衡树,分别用了Splay和fhq-treap交了一遍. 这是Splay的板子,貌似比较短? Splay #include <iostream> #include <cstdio ...

  4. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  5. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  6. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  7. 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会

    平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...

  8. BZOJ3223/洛谷P3391 - 文艺平衡树

    BZOJ链接 洛谷链接 题意 模板题啦~2 代码 //文艺平衡树 #include <cstdio> #include <algorithm> using namespace ...

  9. BZOJ3224/洛谷P3391 - 普通平衡树(Splay)

    BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...

  10. 洛谷 P3391 文艺平衡树

    题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 --b ...

随机推荐

  1. Maven:Failed to read artifact descriptor for xxx

    Maven多模块项目jar包引用问题: Failed to execute goal on project xxx-service: Could not resolve dependencies fo ...

  2. Emoji表情符号兼容方案

    Emoji表情符号兼容方案 一 什么是Emoji    emoji就是表情符号:词义来自日语(えもじ,e-moji,moji在日语中的含义是字符) 表情符号现已普遍应用于手机短信和网络聊天软件. em ...

  3. re模块3

    #分组 () print(re.findall("(ad)/(vv)","adddad/vvdddddddddd")) print(re.findall(&qu ...

  4. UML-测试驱动开发

    1.什么是测试驱动开发? 测试驱动开发(TDD)是迭代和敏捷XP方法提倡的优秀实践,该实践为测试测试优先开发.不仅包含单元测试. 2.为什么测试驱动开发? 1).最大提升代码稳定性 2).澄清接口和行 ...

  5. 寒假day08

    今天爬了部分与人才动态相关的数据,还刷了剑指offer的部分算法题

  6. 视觉slam十四讲个人理解(ch7视觉里程计1)

    参考博文::https://blog.csdn.net/david_han008/article/details/53560736 https://blog.csdn.net/n66040927/ar ...

  7. Vue.js——4.指令 笔记

    v-cloak:解决网速延迟 闪烁问题v-text=msg: 和{{}}表达式一样,没有闪烁问题,但是前后不能加别的,覆盖原本的内容 innerTextv-html=msg:innerHtml,一样可 ...

  8. 《Docekr入门学习篇》——Docker常用命令

    Docker常用命令 Docker镜像管理 搜索镜像:docker search 获取镜像:docker pull 查看镜像:docker images 删除镜像:docker rmi 构建镜像:do ...

  9. 17.3.12---logging日志模块level配置操作

    1----logging日志记录模块的使用和配置 logging模块我们不需要单独再安装,经常要调试程序,记录程序运行过程中的一些信息,手工记录调试信息很麻烦,所以python的logging模块,会 ...

  10. 吴裕雄--天生自然MySQL学习笔记:MySQL简介

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...