【模板】普通平衡树(数据加强版)
传送门
题目背景
本题是 P3369 数据加强版,扩大数据范围并增加了强制在线。
题目的输入、输出和原题略有不同,但需要支持的操作相同。
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些整数,其中需要提供以下操作:
- 插入一个整数 x x x。
- 删除一个整数 x x x(若有多个相同的数,只删除一个)。
- 查询整数 x x x 的排名(排名定义为比当前数小的数的个数 + 1 +1 +1)。
- 查询排名为 x x x 的数(如果不存在,则认为是排名小于 x x x 的最大数。保证 x x x 不会超过当前数据结构中数的总数)。
- 求 x x x 的前驱(前驱定义为小于 x x x,且最大的数)。
- 求 x x x 的后继(后继定义为大于 x x x,且最小的数)。
本题强制在线,保证所有操作合法(操作 2 2 2 保证存在至少一个 x x x,操作 4 , 5 , 6 4,5,6 4,5,6 保证存在答案)。
输入格式
第一行两个正整数 n , m n,m n,m,表示初始数的个数和操作的个数。
第二行 n n n 个整数 a 1 , a 2 , a 3 , … , a n a_1,a_2,a_3,\ldots,a_n a1,a2,a3,…,an,表示初始的数。
接下来 m m m 行,每行有两个整数 opt \text{opt} opt 和 x ′ x' x′, opt \text{opt} opt 表示操作的序号($ 1 \leq \text{opt} \leq 6 ), ), ),x’$ 表示加密后的操作数。
我们记 last \text{last} last 表示上一次 3 , 4 , 5 , 6 3,4,5,6 3,4,5,6 操作的答案,则每次操作的 x ′ x' x′ 都要异或上 last \text{last} last 才是真实的 x x x。初始 last \text{last} last 为 0 0 0。
输出格式
输出一行一个整数,表示所有 3 , 4 , 5 , 6 3,4,5,6 3,4,5,6 操作的答案的异或和。
样例 #1
样例输入 #1
6 7
1 1 4 5 1 4
2 1
1 9
4 1
5 8
3 13
6 7
1 4
样例输出 #1
6
提示
样例解释
样例加密前为:
6 7
1 1 4 5 1 4
2 1
1 9
4 1
5 9
3 8
6 1
1 0
限制与约定
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1≤n≤105, 1 ≤ m ≤ 1 0 6 1\leq m\leq 10^6 1≤m≤106, 0 ≤ a i , x < 2 30 0\leq a_i,x\lt 2^{30} 0≤ai,x<230。
本题输入数据较大,请使用较快的读入方式。
upd 2022.7.22 \text{upd 2022.7.22} upd 2022.7.22:新增加 9 9 9 组 Hack 数据。
注明
以上来自洛谷。 以上来自洛谷。 以上来自洛谷。
有 pb_ds 做法但是不能交题解,太/oh了。
解题思路
前置知识
- pb_ds
- pb_ds内的平衡树用法
正文
提供一种 pb_ds 做法,代码非常短。
因为是平衡树模版,直接使用 pb_ds 即可。注意在输入 x ′ x^{'} x′ 时要异或上上一次 3 , 4 , 5 , 6 3,4,5,6 3,4,5,6 操作的答案;最终答案为所有 3 , 4 , 5 , 6 3,4,5,6 3,4,5,6 操作的答案的异或和;tree 一定!一定!要开 unsigned long long ,long long 左移 20 20 20 位可能会爆。
说完注意点,接下来只有用 pb_ds 库中内置的平衡树实现题目中的相应操作即可。
AC Code
#include<bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define int unsigned long long
int n, m, a[100005];
tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> Tree;
int Answer;
signed main() {ios::sync_with_stdio(false), cin.tie(0), cout.tie(0), cin >> n >> m;for (register int i = 1; i <= n; ++i) cin >> a[i], Tree.insert((a[i] << 20) + i);short opt;int x, last = 0;for (register int i = 1; i <= m; ++i) {cin >> opt >> x, x ^= last;if (opt == 1) Tree.insert((x << 20) + i);else if (opt == 2) Tree.erase(Tree.lower_bound(x << 20));else if (opt == 3) last = Tree.order_of_key(x << 20) + 1, Answer ^= last;else {if (opt == 4) last = *Tree.find_by_order(x - 1);if (opt == 5) last = *--Tree.lower_bound(x << 20);if (opt == 6) last = *Tree.lower_bound((x + 1) << 20);last >>= 20, Answer ^= last;}}cout << Answer << endl;return 0;
}
想想看赛场上其他人调一万年平衡树没调出来但是你用 pb_ds 10 m i n 10min 10min 通过的快感。