treap树(平衡树的其他版本)
\(Treap\) 树性质
具有 \(BST\) 树的二叉搜索性质,又具有堆的性质,从而保证树不退化成一颗链,保证操作都是 \(log\) 级别的。
std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
struct node{
int val;// 这个数的值
int prq;// 这个数的随机值用来维护堆的性质(大根堆或小根堆)
int siz;// 以这个点为根的子树大小
int cnt;// 多少个这样相同的值
int ch[2];// 左右儿子
node(int val = 0, int prq = 0, int siz = 0, int cnt = 0) : val(val), prq(prq), siz(siz), cnt(cnt) {
ch[0] = ch[1] = 0;
}
} tree[N + 1];
int tot;
// 维护
inline void push_up(int p) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
tree[p].siz = tree[ls].siz + tree[rs].siz + tree[p].cnt;
}
// 左右旋
void rotate(int &p, int op) {// op为0表示左旋,op为1表示右旋
int k = tree[p].ch[op ^ 1];
tree[p].ch[op ^ 1] = tree[k].ch[op];
tree[k].ch[op] = p;
push_up(p);// 先维护儿子节点p
push_up(k);// 再维护父亲节点k
p = k;// 根节点变成了k
}
// 插入
inline void ins(int &p, int val) {
if (!p) {
p = ++tot;
tree[p] = node(val, rng() % mof, 1, 1);
return;
}
if (tree[p].val == val) {
tree[p].cnt++;
tree[p].siz++;
return;
}
int op = val > tree[p].val;
int &k = tree[p].ch[op];
ins(k, val);
if (tree[p].prq < tree[tree[p].ch[op]].prq) {
rotate(p, op ^ 1);
}
push_up(p);
}
// 删除
inline void del(int &p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return;
if (tree[p].val > val) {
del(ls, val);
} else if (tree[p].val < val) {
del(rs, val);
} else {
if (!ls && !rs) {// 说明是叶子结点,直接删除
tree[p].siz--;
tree[p].cnt--;
if (tree[p].cnt == 0) {
p = 0;
}
} else if (ls && !rs) {// 将他右旋直到转移到叶子结点上
rotate(p, 1);
del(tree[p].ch[1], val);
} else if (!ls && rs) {// 将他左旋直到转移到叶子结点上
rotate(p, 0);
del(tree[p].ch[0], val);
} else if (ls && rs) {// 左右子树都不为空,找到左子树中最大值或右子树中最小值,然后删除
int d = (tree[ls].prq > tree[rs].prq);
rotate(p, d);
del(tree[p].ch[d], val);
}
}
push_up(p);
}
// 查询某个值的排名
inline int rnk(int p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return 1;
if (tree[p].val == val) return tree[ls].siz + 1;
if (tree[p].val > val) return rnk(ls, val);
if (tree[p].val < val) return tree[ls].siz + tree[p].cnt + rnk(rs, val);
}
// 查询某个排名对应的值
inline int fnd(int p, int rk) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return 0;
if (tree[ls].siz >= rk) {
return fnd(ls, rk);
} else if (tree[ls].siz + tree[p].cnt < rk) {
return fnd(rs, rk - tree[ls].siz - tree[p].cnt);
} else {
return tree[p].val;
}
}
// 查询某个数的前驱
inline int pre(int p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return -inf;
if (tree[p].val >= val) {
return pre(ls, val);
} else {
return max(tree[p].val, pre(rs, val));
}
}
// 查询某个数的后继
inline int nxt(int p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return inf;
if (tree[p].val <= val) {
return nxt(rs, val);
} else {
return min(tree[p].val, nxt(ls, val));
}
}
void print(int p) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (ls) print(ls);
cout << tree[p].val << ' ';
if (rs) print(rs);
}
void solve() {
int n;
cin >> n;
int root = 0;
for (int i = 1; i <= n; i++) {
int op, x;
cin >> op >> x;
if (op == 1) {
ins(root, x);
} else if (op == 2) {
del(root, x);
} else if (op == 3) {
cout << rnk(root, x) << '\n';
} else if (op == 4) {
cout << fnd(root, x) << '\n';
} else if (op == 5) {
cout << pre(root, x) << '\n';
} else if (op == 6) {
cout << nxt(root, x) << '\n';
}
// cout << root << '\n';
// print(root);
// cout << '\n';
}
}
std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
struct node{
int val;// 这个数的值
int prq;// 这个数的随机值用来维护堆的性质(大根堆或小根堆)
int siz;// 以这个点为根的子树大小
int cnt;// 多少个这样相同的值
int ch[2];// 左右儿子
node(int val = 0, int prq = 0, int siz = 0, int cnt = 0) : val(val), prq(prq), siz(siz), cnt(cnt) {
ch[0] = ch[1] = 0;
}
} tree[N + 1];
int a[100005];
int tot;
// 维护
inline void push_up(int p) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
tree[p].siz = tree[ls].siz + tree[rs].siz + tree[p].cnt;
}
// 左右旋
void rotate(int &p, int op) {// op为0表示左旋,op为1表示右旋
int k = tree[p].ch[op ^ 1];
tree[p].ch[op ^ 1] = tree[k].ch[op];
tree[k].ch[op] = p;
push_up(p);// 先维护儿子节点p
push_up(k);// 再维护父亲节点k
p = k;// 根节点变成了k
}
// 插入
inline void ins(int &p, int val) {
if (!p) {
p = ++tot;
tree[p] = node(val, rng() % mof, 1, 1);
return;
}
if (tree[p].val == val) {
tree[p].cnt++;
tree[p].siz++;
return;
}
int op = val > tree[p].val;
int &k = tree[p].ch[op];
ins(k, val);
if (tree[p].prq < tree[tree[p].ch[op]].prq) {
rotate(p, op ^ 1);
}
push_up(p);
}
// 删除
inline void del(int &p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return;
if (tree[p].val > val) {
del(ls, val);
} else if (tree[p].val < val) {
del(rs, val);
} else {
if (!ls && !rs) {// 说明是叶子结点,直接删除
tree[p].siz--;
tree[p].cnt--;
if (tree[p].cnt == 0) {
p = 0;
}
} else if (ls && !rs) {// 将他右旋直到转移到叶子结点上
rotate(p, 1);
del(tree[p].ch[1], val);
} else if (!ls && rs) {// 将他左旋直到转移到叶子结点上
rotate(p, 0);
del(tree[p].ch[0], val);
} else if (ls && rs) {// 左右子树都不为空,找到左子树中最大值或右子树中最小值,然后删除
int d = (tree[ls].prq > tree[rs].prq);
rotate(p, d);
del(tree[p].ch[d], val);
}
}
push_up(p);
}
inline int build(int *L, int n, int cc = 1000000000) {// L从0开始
if (!n) return 0;
int p = ++tot;
tree[p] = node(L[n >> 1], cc - 1 - rand() % 10000, 1, 1);
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
ls = build(L, n >> 1, tree[p].prq);
rs = build(L + (n >> 1) + 1, n - 1 - (n >> 1), tree[p].prq);
push_up(p);
return p;
}
// 查询某个值的排名
inline int rnk(int p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return 1;
if (tree[p].val == val) return tree[ls].siz + 1;
if (tree[p].val > val) return rnk(ls, val);
if (tree[p].val < val) return tree[ls].siz + tree[p].cnt + rnk(rs, val);
}
// 查询某个排名对应的值
inline int fnd(int p, int rk) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return 0;
if (tree[ls].siz >= rk) {
return fnd(ls, rk);
} else if (tree[ls].siz + tree[p].cnt < rk) {
return fnd(rs, rk - tree[ls].siz - tree[p].cnt);
} else {
return tree[p].val;
}
}
// 查询某个数的前驱
inline int pre(int p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return -inf;
if (tree[p].val >= val) {
return pre(ls, val);
} else {
return max(tree[p].val, pre(rs, val));
}
}
// 查询某个数的后继
inline int nxt(int p, int val) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (!p) return inf;
if (tree[p].val <= val) {
return nxt(rs, val);
} else {
return min(tree[p].val, nxt(ls, val));
}
}
void print(int p) {
auto &ls = tree[p].ch[0], &rs = tree[p].ch[1];
if (ls) print(ls);
cout << tree[p].val << ' ';
if (rs) print(rs);
}
void solve() {
int n, q;
read(n, q);
int root = 0;
for (int i = 0; i < n; i++) {
read(a[i]);
}
sort(a, a + n);
root = build(a, n);
int last = 0, ans = 0;
for (int i = 1; i <= q; i++) {
int op, x;
read(op, x);
x ^= last;
if (op == 1) {
ins(root, x);
} else if (op == 2) {
del(root, x);
} else if (op == 3) {
last = rnk(root, x);
ans ^= last;
} else if (op == 4) {
last = fnd(root, x);
ans ^= last;
} else if (op == 5) {
last = pre(root, x);
ans ^= last;
} else if (op == 6) {
last = nxt(root, x);
ans ^= last;
}
}
write(ans, '\n');
}

浙公网安备 33010602011771号