pb_ds简单运用

本文介绍了在算法竞赛中PB_DS数据结构的关键操作,如插入、删除、查找和排序,特别强调了`find_by_order`和`order_of_key`函数及其常数时间复杂度的优势。通过AC代码展示了如何在实际问题中使用PB_DS来优化解决方案。
摘要由CSDN通过智能技术生成

pb_ds详细解释

在算法竞赛中,我们只需要知道pb_ds都有什么操作,每种操作是干什么的即可,不需要了解的太深入

例题

该题可以直接用pb_ds近乎暴力秒杀,以及运用到启发式合并的思想

AC代码

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#include <bits/extc++.h>
using namespace __gnu_pbds;
template <class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
Tree<pair<int, int> > a[200010][2];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        a[0][0].insert(make_pair(x, i));//值,下标
        a[0][1].insert(make_pair(i, x));//下标,值
    }
    int q;
    cin >> q;
    for (int i = 1; i <= q; i++) {
        int t, s, x;
        cin >> t >> s >> x;
        if (t == 1) {
            int num = a[s][1].size();
            x = min(x, num);
            if (2 * x <= num) {
                while (x--) {
                    auto it = a[s][1].begin();
                    a[i][1].insert(*it);
                    a[i][0].insert(make_pair(it->second, it->first));
                    a[s][1].erase(make_pair(it->first, it->second));
                    a[s][0].erase(make_pair(it->second, it->first));
                }
                a[i][0].swap(a[s][0]);
                a[i][1].swap(a[s][1]);
            } else {
                x = num - x;
                while (x--) {
                    auto it = a[s][1].rbegin();
                    a[i][1].insert(*it);
                    a[i][0].insert(make_pair(it->second, it->first));
                    a[s][1].erase(make_pair(it->first, it->second));
                    a[s][0].erase(make_pair(it->second, it->first));
                }
            }
        } else {
            int num = a[s][0].size();
            x = a[s][0].order_of_key(make_pair(x, n + 1));
            if (2 * x <= num) {
                while (x--) {
                    auto it = a[s][0].begin();
                    a[i][0].insert(*it);
                    a[i][1].insert(make_pair(it->second, it->first));
                    a[s][0].erase(make_pair(it->first, it->second));
                    a[s][1].erase(make_pair(it->second, it->first));
                }
                a[i][0].swap(a[s][0]);
                a[i][1].swap(a[s][1]);
            } else {
                x = num - x;
                while (x--) {
                    auto it = a[s][0].rbegin();
                    a[i][0].insert(*it);
                    a[i][1].insert(make_pair(it->second, it->first));
                    a[s][0].erase(make_pair(it->first, it->second));
                    a[s][1].erase(make_pair(it->second, it->first));
                }
            }
        }
        cout << a[i][0].size() << '\n';
    }
    return 0;
}

定义pb_ds方式

//头文件必须包含
#include <bits/extc++.h>
using namespace __gnu_pbds;
//定义模板
template <class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, 
             tree_order_statistics_node_update>;
Tree<pair<int, int> > a[200010][2];
//直接定义
tree<pair<int, int>, null_type, less<pair<int, int> >, rb_tree_tag,
tree_order_statistics_node_update> a[200010][2];

pb_ds可以直接当作set进行操作,其中insert和erase没有区别

其中最关键的是它的swap()的时间复杂度是常数

find_by_order(k)//找到下标从0开始的第k大(第0大,第1大....)
order_of_key(k)//返回严格小于k的数的数量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值