洛谷-普通平衡树 【pbds】

题目链接:https://www.luogu.org/problemnew/show/P3369

使用教程:https://baijiahao.baidu.com/s?id=1610302746201562113&wfr=spider&for=pc

tree差不多可以当作强化版set来用吧。

/// int类型
/// null_type为映射类型, 低版本g++为 null_mapped_type
/// less<int>, greater<int> 比较器
/// rb_tree_tag 和 splay_tree_tag 选择树的类型
/// tree_order_statistics_node_update 结点更新

/// insert, erase
/// order_of_key       查询rank 返回值
/// find_by_order()    查询 kth 返回迭代器
/// lower_bound() 前继, >=x 最小的迭代器
/// upper_bound() 后继   >x  最小的迭代器
/// a.join(b) b并入a,前提是两颗树的取值范围不相交
/// a.split(v, b) key <= v的属于a,其他属于
/// 注意,插入的元素会去重,如set

///显然迭代器可以++,--运算

#include<bits/stdc++.h>
//#include<bits/extc++.h> //include全部文件,但是好像不能用
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp> //用tree
#include<ext/pb_ds/hash_policy.hpp> //用hash
#include<ext/pb_ds/priority_queue.hpp> //用priority_queue
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define ll long long
using namespace std;
using namespace __gnu_pbds;
tree<ll,null_type, less<ll> ,rb_tree_tag,tree_order_statistics_node_update> T;
int main() {
    freopen("a.txt","r",stdin);
    ios::sync_with_stdio(0);
    int n;
    cin>>n;
    rep(i, 1, n) {
        int oper;
        ll x;
        cin>>oper>>x;
        if(oper==1) T.insert((x<<20)+i);
        if(oper==2) T.erase(T.lower_bound(x<<20));
        if(oper==3) cout<<T.order_of_key(x<<20)+1<<endl;
        ll ans = -1e9;
        if(oper==4) ans = *T.find_by_order(x-1);
        if(oper==5) ans = *--T.lower_bound(x<<20);
        if(oper==6) ans = *T.lower_bound((x+1)<<20);
        if(ans!=-1e9) cout<<(ans>>20)<<endl;
    }
    return 0;
}

 

Pbds全称为Perfectly Balanced Red-Black Tree,是一种平衡查找树的数据结构,它是C++标准库中的`<ext/pb_ds/rb_tree>`模块提供的一种高级模板容器,主要用于高效地存储和查找数据。它是在红黑树基础上进行了优化,保证了常数级的平均时间复杂度。 **特点:** 1. **自平衡**:插入、删除操作后的调整过程保证了树的高度最大为log(n),这使得查询操作的时间复杂度保持在O(log n)。 2. **内存效率高**:支持迭代器,可以像普通的数组或vector一样访问元素。 3. **模板化**:适用于各种数据类型,并支持自定义比较函数。 **实践示例(C++17开始引入std::any,旧版本需第三方库如Boost):** ```cpp #include <ext/pb_ds/tree_policy.hpp> // 引入PBDS策略 using namespace __gnu_pbds; // 使用namespace // 定义一个关联值类型的树模板,键为int,值为std::string template <typename K, typename V> using rb_tree = tree<K, null_type, less<K>, rb_tree_tag, tree_order_statistics_node_update>; int main() { // 创建一个rb_tree实例 rb_tree<int, std::string> myTree; // 插入元素 myTree.insert({5, "Hello"}); myTree.insert({10, "World"}); // 查找最小值 auto it = myTree.begin(); if (it != myTree.end()) { std::cout << "Smallest key is " << *it.first << " with value " << it->second << '\n'; } // 计算第3大的值 auto third_largest = myTree.order_of_key(3); // 获取值为3之前的所有节点个数 if (third_largest > 0) { it = myTree.lower_bound(third_largest); if (it != myTree.end()) { std::cout << "Third largest key is " << *it.first << " with value " << it->second << '\n'; } } return 0; } ``` **相关问题--:** 1. Pbds的红黑树相比标准的红黑树有哪些优势? 2. 如何使用Pbds的rb_tree进行范围查找? 3. 在实际项目中,何时会选择使用Pbds而不是普通的二叉搜索树?
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值