【数据结构】无旋Treap
维护翻转操作
struct Treap {
private:
static const int MAXN = 200000 + 10;
int ls[MAXN], rs[MAXN];
int rnd[MAXN], siz[MAXN];
int del[MAXN], dnt;
int cnt, root;
int val[MAXN];
ll sum[MAXN];
bool rev[MAXN];
int NewNode(int v) {
int o = dnt ? del[dnt--] : ++cnt;
ls[o] = 0, rs[o] = 0;
rnd[o] = rand(), siz[o] = 1;
val[o] = v, sum[o] = (ll)v;
rev[o] = 0;
return o;
}
void PushUp(int o) {
siz[o] = siz[ls[o]] + siz[rs[o]] + 1;
sum[o] = sum[ls[o]] + sum[rs[o]] + val[o];
}
void PushDown(int o) {
if(rev[o]) {
swap(ls[o], rs[o]);
rev[ls[o]] ^= 1;
rev[rs[o]] ^= 1;
rev[o] = 0;
}
}
void SplitRank(int o, int rnk, int &x, int &y) {
if(!o) {
x = 0, y = 0;
return;
}
PushDown(o);
if(rnk <= siz[ls[o]]) {
y = o;
SplitRank(ls[o], rnk, x, ls[o]);
PushUp(y);
} else {
x = o;
SplitRank(rs[o], rnk - siz[ls[o]] - 1, rs[o], y);
PushUp(x);
}
}
int Merge(int x, int y) {
if(!x || !y)
return x | y;
PushDown(x), PushDown(y);
if(rnd[x] < rnd[y]) {
rs[x] = Merge(rs[x], y);
PushUp(x);
return x;
} else {
ls[y] = Merge(x, ls[y]);
PushUp(y);
return y;
}
}
public:
void Clear() {
dnt = 0, cnt = 0;
root = NewNode(0);
siz[root] = 0;
}
void Insert(int rnk, int v) {
int L1 = 0, R1 = 0;
SplitRank(root, rnk - 1, L1, R1);
L1 = Merge(L1, NewNode(v));
root = Merge(L1, R1);
}
void Erase(int rnk) {
int L1 = 0, R1 = 0;
SplitRank(root, rnk - 1, L1, R1);
int L2 = 0, R2 = 0;
SplitRank(R1, 1, L2, R2);
R1 = R2, del[++dnt] = L2;
root = Merge(L1, R1);
}
int Value(int rnk) {
int L1 = 0, R1 = 0;
SplitRank(root, rnk - 1, L1, R1);
int L2 = 0, R2 = 0;
SplitRank(R1, 1, L2, R2);
int res = val[L2];
R1 = Merge(L2, R2);
root = Merge(L1, R1);
return res;
}
void Reverse(int l, int r) {
int L1 = 0, R1 = 0;
SplitRank(root, l - 1, L1, R1);
int L2 = 0, R2 = 0;
SplitRank(R1, r - l + 1, L2, R2);
rev[L2] ^= 1;
R1 = Merge(L2, R2);
root = Merge(L1, R1);
}
} treap;
无旋Treap,常用于维护序列,虽然Splay也可以做。
最大优势:在线,时空复杂度基于元素数量,可以可持久化
与离线离散化的权值线段树相比:在线
与动态开点的权值线段树/01Trie相比:时空复杂度基于元素数量,相对更节省,且写起来简单
与其他平衡树相比:可以可持久化
综上所述,这是一个非常优秀的数据结构,其不可替代性非常强