__gnu_pbds::tree

牛客暑期多校第一场
被标为“简单”的题目直接上数据结构了,真TM难
但也算是学到了一个东西,__gnu_pbds::tree
可以简称为pbds平衡树


pbds库相当于C++的STL标准库,提供了一些内置的数据结构
比如优先队列、哈希表、平衡树,用的相对多的就是这个平衡树了
首先,新的万能头文件#include <bits/extc++.h>

  #include <bits/extc++.h>

然后咱们用using简化一下

  using i64 = long long;
  using namespace __gnu_pbds;
  using ordered_set = tree<i64, null_type, std::less<i64>, rb_tree_tag, tree_order_statistics_node_update>;
  using ordered_multiset = tree<i64, null_type, std::less_equal<i64>, rb_tree_tag, tree_order_statistics_node_update>;

乍一看会觉得,什么玩意,这麽长,怎么记得住的
但这个无所谓,咱们只需要拿过来然后使用就ok了
和常规的STL一样,咱们只需要学会“背单词”即可


首先,插入,bt.insert()
和set容器一样,插入用的是insert

  int n;
  std::cin >> n;

  std::vector<int> a(n + 1);
  ordered_multiset bt;

  for (int i = 1; i <= n; i++) {
      std::cin >> a[i];
      bt.insert(a[i]);
  }


其次,删除,bt.erase()
这里也是和set容器一样,但是我们不建议直接删元素
而是“删除该元素在数组中第一次出现的位置上的元素”
这样更为严谨,且不易出错

  int cnt;
  bt.erase(bt.lower_bound(cnt));


接下来,平衡树最重要的,当然还是查询元素了
查询元素在序列中是第几大,或者查询第k大的元素是谁,都需要用到平衡树
bt.order_of_key(x):返回严格小于 x 的元素个数,即从 0 开始的排名

  int num;
  std::cin >> num;
  // 这里返回的是有多少个元素严格小于num,故相当于从0开始的排名
  int id = bt.order_of_key(num);

bt.find_by_order(x):返回排名所对应元素的迭代器

  int k;
  std::cin >> k;
  // 因为find_by_order()函数返回的是指针类型,所以需要在前面加*,这样才是具体数值
  auto it = bt.find_by_order(k);
  int res = *bt.find_by_order(k);


最后就是一些比较常规的了
bt.size():返回平衡树大小
bt.empty():返回是否为空
所有操作的时间复杂度都是 <= O(logn)级别的,可以通过绝大多数的题目
另外,upper_bound()和lower_bound()的作用不再赘述
但最最重要的是,在使用less_equal<>时,这两个函数在pbds平衡树里功能互换!!


今天L题,其实思路也不算难,但没平衡树的话代码确实不好实现

点击查看代码
#include <bits/stdc++.h>
#include <bits/extc++.h>

#define debug(x) std::cout << #x << " = " << x << '\n'
#define debugp(x, y) std::cout << #x << ", " << #y << " = " << "[" << x << ", " << y << "]\n"
#define debugt(x, y, z) std::cout << #x << ", " << #y << ", " << #z << " = " << "[" << x << ", " << y << ", " << z << "]\n"
#define debug1(f, a, b) std::cout << #f << ": "; for (int i = (a); i <= (b); i++) std::cout << (f)[i] << " \n"[i == (b)]
#define debug2(f, a, b, c, d) std::cout << #f << ":\n"; for (int i = (a); i <= (b); i++) for (int j = (c); j <= (d); j++) std::cout << (f)[i][j] << " \n"[j == (d)]
#define debug_1(q) std::cout << #q << ": ";  for (auto it : (q)) std::cout << it << ' '; std::cout << '\n'
#define debug_2(q) std::cout << #q << ":\n"; for (auto [x, y] : (q)) std::cout << '[' << x << ", " << y << "]\n"
#define debug_3(q) std::cout << #q << ":\n"; for (auto [x, y, z] : (q)) std::cout << '[' << x << ", " << y << ", " << z << "]\n"  
#define show(q) std::cout << #q << ": "; while ((q).size()) { std::cout << (q).top() << ' '; (q).pop(); } std::cout << '\n';

using i64 = int64_t;
using namespace __gnu_pbds;
using ordered_set = __gnu_pbds::tree<i64, null_type, std::less<i64>, rb_tree_tag, tree_order_statistics_node_update>;
using ordered_multiset = __gnu_pbds::tree<i64, null_type, std::less_equal<i64>, rb_tree_tag, tree_order_statistics_node_update>;

constexpr int N = 2e5 + 10;
constexpr int inf = INT_MAX;
constexpr i64 INF = LLONG_MAX;
constexpr int mod = 998244353;

//====================Solution-bg====================//

void solve() {
    int n, q;
    std::cin >> n >> q;
 
    std::vector<i64> a(n + 1);
    ordered_multiset bt;
 
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        bt.insert(a[i]);
    }
 
    while (q--) {
        i64 u, v;
        std::cin >> u >> v;
 
        bt.erase(bt.upper_bound(a[u]));
        a[u] += v;
        bt.insert(a[u]);
 
        int res = n / 2;
        int tmp = *bt.find_by_order(bt.size() - res);  
         
        int id = bt.order_of_key(tmp);
        std::cout << id << '\n';
    }
}

//====================Solution-ed====================//

int32_t main () {   
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t = 1;
    std::cin >> t;

    while (t--) {
        solve();
    }
    
    return 0;
}

哎我草我为什么不能早点知道这些东西捏,直接少走几十天弯路(bushi)

posted @ 2025-07-15 20:21  _彩云归  阅读(77)  评论(1)    收藏  举报