WBLT
放兩個題的 Code 先。
普通平衡樹(資料加強版)
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x), ___ = (y); i <= ___; i++)
#define per(i, x, y) for (int i = (x), ___ = (y); i >= ___; i--)
inline int read() {
char ch = getchar(); int s = 0, f = 1;
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return s * f;
}
constexpr int N = 2e6 + 2e5 + 100;
namespace WBLT {
int tot, ls[N], rs[N], val[N], sz[N];
constexpr double alpha = 0.292;
inline void copy(int x, int y) {
ls[x] = ls[y], rs[x] = rs[y];
sz[x] = sz[y], val[x] = val[y];
}
inline int add(int x, int siz, int lson, int rson) {
ls[++tot] = lson, rs[tot] = rson;
sz[tot] = siz, val[tot] = x;
return tot;
}
inline int addfa(int x, int y) { return add(val[y], sz[x] + sz[y], x, y); }
inline void pushup(int id) {
if (!ls[id]) return (void)(sz[id] = 1);
sz[id] = sz[ls[id]] + sz[rs[id]];
val[id] = val[rs[id]];
}
inline void rotate(int id, bool dir) {
// dir = 0, L -> R
// dir = 1, R -> L
int ori = 0;
if (!dir) {
rs[id] = addfa(rs[ls[id]], rs[id]);
ori = ls[id]; ls[id] = ls[ls[id]];
copy(ori, rs[id]), rs[id] = ori, tot--;
} else {
ls[id] = addfa(ls[id], ls[rs[id]]);
ori = rs[id]; rs[id] = rs[rs[id]];
copy(ori, ls[id]), ls[id] = ori, tot--;
}
}
inline void maintain(int id) {
if (!ls[id]) return ;
if (sz[ls[id]] > sz[rs[id]]) {
if (sz[rs[id]] >= sz[id] * alpha) return ;
if (sz[rs[ls[id]]] >= sz[ls[id]] * (1 - alpha * 2) / (1 - alpha)) rotate(ls[id], 1);
rotate(id, 0);
} else {
if (sz[ls[id]] >= sz[id] * alpha) return ;
if (sz[ls[rs[id]]] >= sz[rs[id]] * (1 - alpha * 2) / (1 - alpha)) rotate(rs[id], 0);
rotate(id, 1);
}
}
void insert(int id, int x) {
if (!ls[id]) {
ls[id] = add(min(x, val[id]), 1, 0, 0);
rs[id] = add(max(x, val[id]), 1, 0, 0);
pushup(id); maintain(id);
return ;
}
if (val[ls[id]] >= x) insert(ls[id], x);
else insert(rs[id], x);
pushup(id); maintain(id);
}
void erase(int id, int x, int fa = -1) {
if (!ls[id]) {
if (val[ls[fa]] == x) copy(fa, rs[fa]);
else if (val[rs[fa]] == x) copy(fa, ls[fa]);
return ;
}
if (val[ls[id]] >= x) erase(ls[id], x, id);
else erase(rs[id], x, id);
pushup(id); maintain(id);
}
int rnk(int id, int x) {
if (!ls[id]) return 1;
if (val[ls[id]] >= x) return rnk(ls[id], x);
return rnk(rs[id], x) + sz[ls[id]];
}
int kth(int id, int x) {
if (sz[id] == x) return val[id];
if (sz[ls[id]] >= x) return kth(ls[id], x);
return kth(rs[id], x - sz[ls[id]]);
}
inline int pre(int rt, int x) { return kth(rt, rnk(rt, x) - 1); }
inline int suf(int rt, int x) { return kth(rt, rnk(rt, x + 1)); }
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("opuntia.in", "r", stdin);
freopen("opuntia.out", "w", stdout);
#endif
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n = read(), qq = read(), rt = WBLT::add(2e9, 1, 0, 0), ans = 0, Ans = 0;
while (n--) {
int x = read();
WBLT::insert(rt, x);
}
while (qq--) {
int op = read(), x = read() ^ ans;
if (op == 1) WBLT::insert(rt, x);
else if (op == 2) WBLT::erase(rt, x);
else if (op == 3) Ans ^= (ans = WBLT::rnk(rt, x));
else if (op == 4) Ans ^= (ans = WBLT::kth(rt, x));
else if (op == 5) Ans ^= (ans = WBLT::pre(rt, x));
else Ans ^= (ans = WBLT::suf(rt, x));
}
cout << Ans;
return 0;
}
文藝平衡樹
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (int i = (x), ___ = (y); i <= ___; i++)
#define per(i, x, y) for (int i = (x), ___ = (y); i >= ___; i--)
inline int read() {
char ch = getchar(); int s = 0, f = 1;
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return s * f;
}
namespace WBLT {
constexpr int N = 2e5 + 100;
int tot, ls[N], rs[N], val[N], sz[N]; bool rev[N];
vector<int> cur;
constexpr double alpha = 0.25;
inline void copy(int x, int y) {
ls[x] = ls[y], rs[x] = rs[y];
sz[x] = sz[y], val[x] = val[y];
}
inline int add(int x, int siz, int lson, int rson) {
if (cur.size()) {
int id = cur.back(); cur.pop_back();
ls[id] = lson, rs[id] = rson;
sz[id] = siz, val[id] = x;
return id;
}
ls[++tot] = lson, rs[tot] = rson;
sz[tot] = siz, val[tot] = x;
return tot;
}
inline int addfa(int x, int y) { return add(val[y], sz[x] + sz[y], x, y); }
inline void pushup(int id) {
if (!ls[id]) return (void)(sz[id] = 1);
sz[id] = sz[ls[id]] + sz[rs[id]];
val[id] = val[rs[id]];
}
inline void pushdown(int id) {
if (!rev[id] || !ls[id]) return ;
swap(ls[id], rs[id]);
rev[ls[id]] ^= 1, rev[rs[id]] ^= 1;
rev[id] = 0;
}
inline void rotate(int id, bool dir) {
// dir = 0, L -> R
// dir = 1, R -> L
int ori = 0;
if (!dir) {
rs[id] = addfa(rs[ls[id]], rs[id]);
ori = ls[id]; ls[id] = ls[ls[id]];
copy(ori, rs[id]), rs[id] = ori, tot--;
} else {
ls[id] = addfa(ls[id], ls[rs[id]]);
ori = rs[id]; rs[id] = rs[rs[id]];
copy(ori, ls[id]), ls[id] = ori, tot--;
}
}
inline void maintain(int id) {
if (!ls[id]) return ;
if (min(sz[ls[id]], sz[rs[id]]) >= sz[id] * alpha) return ;
pushdown(id), pushdown(ls[id]), pushdown(rs[id]);
if (sz[ls[id]] >= sz[rs[id]]) {
if (sz[rs[ls[id]]] >= sz[ls[id]] * (1 - alpha * 2) / (1 - alpha)) rotate(ls[id], 1);
rotate(id, 0);
} else {
if (sz[ls[rs[id]]] >= sz[rs[id]] * (1 - alpha * 2) / (1 - alpha)) rotate(rs[id], 0);
rotate(id, 1);
}
}
void insert(int id, int x) {
if (!ls[id]) {
ls[id] = add(min(x, val[id]), 1, 0, 0);
rs[id] = add(max(x, val[id]), 1, 0, 0);
pushup(id); maintain(id);
return ;
}
if (val[ls[id]] >= x) insert(ls[id], x);
else insert(rs[id], x);
pushup(id); maintain(id);
}
int merge(int x, int y) {
if (!x || !y) return x ^ y;
if (min(sz[x], sz[y]) >= (sz[x] + sz[y]) * alpha) return addfa(x, y);
pushdown(x), pushdown(ls[x]), pushdown(rs[x]);
pushdown(y), pushdown(ls[y]), pushdown(rs[y]);
if (sz[x] >= sz[y]) {
if (sz[ls[x]] >= (sz[x] + sz[y]) * alpha) {
cur.push_back(x);
int lson = ls[x], rson = rs[x];
return merge(lson, merge(rson, y));
} else {
cur.push_back(x), cur.push_back(rs[x]);
int lson = ls[x], lrson = ls[rs[x]], rrson = rs[rs[x]];
return merge(merge(lson, lrson), merge(rrson, y));
}
} else {
if (sz[rs[y]] >= (sz[x] + sz[y]) * alpha) {
cur.push_back(y);
int lson = ls[y], rson = rs[y];
return merge(merge(x, lson), rson);
} else {
cur.push_back(ls[y]), cur.push_back(y);
int llson = ls[ls[y]], rlson = rs[ls[y]], rson = rs[y];
return merge(merge(x, llson), merge(rlson, rson));
}
}
}
void split(int id, int k, int &x, int &y) {
if (!k) return (void)(x = 0, y = id);
if (!ls[id]) return (void)(x = id, y = 0);
pushdown(id); cur.push_back(id);
if (sz[ls[id]] >= k) {
int rson = rs[id];
split(ls[id], k, x, y);
y = merge(y, rson);
} else {
int lson = ls[id];
split(rs[id], k - sz[ls[id]], x, y);
x = merge(lson, x);
}
}
void print(int id) {
if (!ls[id]) return (void)(cout << val[id] << ' ');
pushdown(id); print(ls[id]), print(rs[id]);
}
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("opuntia.in", "r", stdin);
freopen("opuntia.out", "w", stdout);
#endif
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n = read(), qq = read(), rt = WBLT::add(n--, 1, 0, 0), x, y, z, ans = 0, Ans = 0;
while (n--) WBLT::insert(rt, n + 1);
while (qq--) {
int l = read(), r = read();
WBLT::split(rt, l - 1, x, y);
WBLT::split(y, r - l + 1, y, z);
WBLT::rev[y] ^= 1;
rt = WBLT::merge(x, WBLT::merge(y, z));
}
WBLT::print(rt);
return 0;
}