__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)