首页 > 其他分享 >[学习笔记] 树套树学习笔记

[学习笔记] 树套树学习笔记

时间:2024-11-03 20:58:10浏览次数:3  
标签:sz 树套 int 线段 笔记 学习 区间 平衡

哎,今天立了个 flag,那就先学一个树套树吧。

线段树套平衡树

  • 前置芝士:线段树、平衡树、二分答案

顾名思义,线段树套平衡树是给线段树的每个节点都建一颗平衡树。我们先不考虑空间复杂度的问题。

那么它一般用来解决什么问题呢?首先,线段树一般是用来维护序列的区间操作的,而平衡树一般针对于非区间操作复杂问题。所以当二者结合起来,相当于我们要维护一个序列,并且可以解决区间操作复杂问题,该怎么办呢?

换言之,我们需要用线段树维护区间操作,但区间内需要维护的东西又是需要平衡树来解决的,这时候我们就需要使用线段树套平衡树来解决。

如果有读者不理解复杂问题,可以参考以下的例子:对于序列第 \(k\) 小问题,我们无法使用普通的线段树操作。

好了,我们从一到模板题入手。

Link

我们需要实现一种数据结构,来支持:

  • 单点修改

  • 查询区间第 \(k\) 小

  • 查询 \(p\) 在区间里的排名

  • 查询区间内的前驱和后继

这道题中,如果把“区间”二字去掉,就成了普通的平衡树问题。所以这道题是需要我们解决区间操作复杂问题,考虑使用线段树套平衡树。

由于外层是线段树,我们按照线段树的方式来讨论。平衡树建议使用 Fhq-Treap。

1. 建树

我们每次对于表示区间 \([l, r]\) 的线段树节点 \(u\) 建树时,把 \(a_i, i \in [l, r]\) 插入到这个节点对应的平衡树中。

这里面的平衡树建议用一个结构体封装。至于空间复杂度的问题,我们考虑建一个平衡树森林,然后对于每颗平衡树,只需要记录它的根即可。

平衡树代码:

平衡树
int n, ts, a[N];

struct node{
    int ls, rs;
    int ky, vl, sz;
}t[M];
struct treap{
    int rt;
    void pushup(int u) {
	    t[u].sz = t[t[u].ls].sz + t[t[u].rs].sz + 1;
    }
    void mknode(int x) {
	    ++ts;
	    t[ts] = (node){0, 0, x, rand(), 1};
    }
    void split(int u, int x, int &l, int &r) {
    	if (!u) {
    		l = r = 0;
	    	return ;
    	}
    	if (t[u].ky <= x) {
	    	l = u;
	    	split(t[u].rs, x, t[u].rs, r);
	    } else {
	    	r = u;
	    	split(t[u].ls, x, l, t[u].ls);
	    }
	    pushup(u);
    }
    int merge(int l, int r) {
	    if (!l || !r) return l + r;
    	if (t[l].vl < t[r].vl) {
	    	t[r].ls = merge(l, t[r].ls);
	    	pushup(r);
	    	return r;
    	} else {
	    	t[l].rs = merge(t[l].rs, r);
	    	pushup(l);
	    	return l;
	    }
    }
    void ins(int x) {
    	int l, r;
    	split(rt, x, l, r);
	    mknode(x);
	    rt = merge(l, merge(ts, r));
    }
    void del(int x) {
	    int a, b, c;
    	split(rt, x - 1, a, b);
	    split(b, x, b, c);
	    b = merge(t[b].ls, t[b].rs);
    	rt = merge(a, merge(b, c));
    }
    int grk(int x) {
    	int l, r, res;
	    split(rt, x - 1, l, r);
    	res = t[l].sz + 1;
	    rt = merge(l, r);
	    return res;
    }
    int kth(int u, int k) {
	    if (k == t[t[u].ls].sz + 1) return u;
	    if (k <= t[t[u].ls].sz) return kth(t[u].ls, k);
	    return kth(t[u].rs, k - t[t[u].ls].sz - 1);
    }
    int pre(int x) {
    	int l, r, res;
    	split(rt, x - 1, l, r);
        if (!t[l].sz) res = -I;
	    else res = t[kth(l, t[l].sz)].ky;
	    rt = merge(l, r);
	    return res;
    }
    int suc(int x) {
    	int l, r, res;
	    split(rt, x, l, r);
        if (!t[r].sz) res = I;
 	    else res = t[kth(r, 1)].ky;
	    rt = merge(l, r);
	    return res;
    }
    void build(int l, int r) {
        for (int i = l; i <= r; i++) {
            ins(a[i]);
        }
    }
}ft[N << 2];

标签:sz,树套,int,线段,笔记,学习,区间,平衡
From: https://www.cnblogs.com/Eliauk-FP/p/18523959

相关文章

  • 【python-程序设计赛道-模拟题笔记整理】2024年第六届全国高校计算机能力挑战赛
    Python知识点整理不都正确是指要求找错误的如果没有错误的,全都是事实就没有符合题意的所以选选项D,三个选项不都正确模块模块不能被多次导入模块是构造程序的方式在执行时,一个模块只会被导入一次python程序文件是一个模块包语法空行不是python语法的一部分缩进是p......
  • 学期(如2024-2025-1) 20241406刘书含)《计算机基础与程序设计》第六周学习总结
    教材学习内容总结《计算机科学概论》第七章计算机硬件基础:计算机硬件是计算机系统的物质基础,包括中央处理器(CPU)、内存、存储设备、输入输出设备等。中央处理器(CPU):CPU是计算机的大脑内存:内存(RAM)是计算机的短期记忆,用于存储当前正在处理的数据和程序。包括随机访问存储器(RAM......
  • 深度学习:卷积神经网络中的im2col
    im2col是一种在卷积神经网络(CNN)中常用的技术,用于将输入图像数据转换为适合卷积操作的矩阵形式。通过这种转换,卷积操作可以被高效地实现为矩阵乘法,从而加速计算。在传统的卷积操作中,卷积核(滤波器)在输入图像上滑动,逐个计算每个位置的卷积结果。这种操作在计算上非常耗时,尤其......
  • 你还在因为学不会Java而烦恼吗?宝贝,我这有一篇关于Java的学习方法,你确定不来看看吗?
    Java学习方案1.学习目标初级目标:掌握Java基础语法,能够编写简单的程序。中级目标:熟悉面向对象编程(OOP)和常用API,能够开发中小型应用。高级目标:深入理解Java高级特性,掌握多线程、网络编程、框架使用等,能够开发大型企业级应用。2.学习路径2.1基础知识Java安装与配置......
  • 2024-2025-1 20241318《计算机基础与程序设计》第六周学习总结
    这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK06这个作业的目标<Polya如何解决问题简单类型与组合类型复合数据结构查找与排序算法算法复杂度......
  • 《计算机基础与程序设计》第6周学习总结
    学期2024-2025-1学号20241414《计算机基础与程序设计》第6周学习总结作业信息这个作业属于哪个课程2024-2025-1-计算机基础与程序设计这个作业要求在哪里2024-2025-1计算机基础与程序设计第6周作业这个作业的目标1.循环语句2.循环语句的具体运用3.第二次实验4.函......
  • 关联容器笔记
    关联容器总结有序关联容器键值的顺序自动排序,键值必须支持<操作符底层数据结构使用平衡树,比如(红黑树)增删查的平均时间复杂度接近O(log⁡n)种类std::set:集合,包含唯一的键元素。std::multiset:多重集合,允许键重复。std::map:映射,键值对(键唯一,值可以重复)。std::m......
  • 大数据学习笔记 第4天 Shell编程基础高级实战详解
    Shell一、Shell编程概述Shell本身并不是内核的一部分,它只是站在内核的基础上编写的一个应用程序。用户通过Shell来使用Linux,不启动Shell的话,用户就没办法使用Linux。在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(commandinterpr......
  • # 学期2024-2025-1 学号20241405《计算机基础与程序设计》6周学习总结
    作业信息这个作业属于哪个课程<班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如[2024-2025-1计算机基础与程序设计第六周作业](https://www.cnblogs.com/rocedu/p/9577842.html#WEEK06作业正文C语言是一种过程式编程语言,它提......