【LG5055】可持久化文艺平衡树
【LG5055】可持久化文艺平衡树
题面
题解
终于不可以用\(Trie\)水了。。。
和普通的\(FHQ\;treap\)差不多
注意一下\(pushdown\)、\(split\)要新开节点
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 2e5 + 5;
struct Node {
int ls, rs, pri, val, size;
long long sum;
bool rev;
} t[MAX_N << 6];
int rub[MAX_N << 6], cur, rubtop, rt[MAX_N];
inline int newNode(int v = 0) {
int o = rubtop ? rub[rubtop--] : ++cur;
t[o].val = t[o].sum = v; t[o].pri = rand(); t[o].size = 1;
t[o].ls = t[o].rs = t[o].rev = 0;
return o;
}
inline int clone(int y) {
int x = rubtop ? rub[rubtop--] : ++cur;
t[x] = t[y];
return x;
}
inline void pushup(int o) {
t[o].size = t[t[o].ls].size + t[t[o].rs].size + 1;
t[o].sum = t[t[o].ls].sum + t[t[o].rs].sum + t[o].val;
}
inline void pushdown(int o) {
if (!t[o].rev) return ;
swap(t[o].ls, t[o].rs);
if (t[o].ls) t[o].ls = clone(t[o].ls), t[t[o].ls].rev ^= 1;
if (t[o].rs) t[o].rs = clone(t[o].rs), t[t[o].rs].rev ^= 1;
t[o].rev = 0;
}
void split(int o, int k, int &ls, int &rs) {
if (!o) ls = rs = 0;
else {
pushdown(o);
if (k <= t[t[o].ls].size) rs = clone(o), split(t[rs].ls, k, ls, t[rs].ls), pushup(rs);
else ls = clone(o), split(t[ls].rs, k - t[t[o].ls].size - 1, t[ls].rs, rs), pushup(ls);
}
}
int merge(int x, int y) {
if (!(x && y)) return x ^ y;
if (t[x].pri < t[y].pri) {
pushdown(y);
t[y].ls = merge(x, t[y].ls);
pushup(y);
return y;
} else {
pushdown(x);
t[x].rs = merge(t[x].rs, y);
pushup(x);
return x;
}
}
void insert(int &o, int k, int v) {
int x, y;
split(o, k, x, y);
o = merge(merge(x, newNode(v)), y);
}
void erase(int &o, int pos) {
int x, y, z;
split(o, pos, x, z);
split(x, pos - 1, x, y);
rub[++rubtop] = y;
o = merge(x, z);
}
void reverse(int &o, int l, int r) {
int x, y, z;
split(o, r, x, z);
split(x, l - 1, x, y);
t[y].rev ^= 1;
o = merge(merge(x, y), z);
}
long long query(int &o, int l, int r) {
int x, y, z;
split(o, r, x, z);
split(x, l - 1, x, y);
long long res = t[y].sum;
o = merge(merge(x, y), z);
return res;
}
long long ans = 0;
int N;
int main () {
srand(19260817);
N = gi();
for (int i = 1; i <= N; i++) {
int v = gi(), op = gi();
rt[i] = rt[v];
if (op == 1) { int k = gi() ^ ans, val = gi() ^ ans; insert(rt[i], k, val); }
else if (op == 2) { int k = gi() ^ ans; erase(rt[i], k); }
else if (op == 3) { int l = gi() ^ ans, r = gi() ^ ans; reverse(rt[i], l, r); }
else { int l = gi() ^ ans, r = gi() ^ ans; printf("%lld\n", ans = query(rt[i], l, r)); }
}
return 0;
}