可持久化FHQ
后言
-
为什么只需要在 split 的时候可持久化就可以了 而不用在合并的时候再做一次?
- 因为,我们一次操作,都会先分裂,而我们只关心对一次操作之后的状态保留下来。所以合并的时候即使改变了状态也无所谓,因为我们并不关心中间的版本,而若是,分裂之后的状态也是有用的,那么我们合并也需要可持久化了。
-
还有就是,由于我们涉及到了可持久化,操作,必不可少的需要在 down 的时候对儿子复制一遍。若是平衡树的话就可能导致没有儿子,但硬生生新加了一个编号为 0 的儿子,所以down的时候需要特判一下。
-
参考实现
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <random>
using namespace std;
typedef long long ll;
mt19937 Rand;
const int N = 200200, M = N * 100;
struct node
{
unsigned int k; int size, val; ll sum;
int ls, rs, rev;
}t[M]; int idx;
void rev(int x) { if (x)t[x].rev ^= 1; }
void copynode(int& x) { idx++; t[idx] = t[x]; x = idx; }
int newnode(int v) { idx++; t[idx].k = Rand(); t[idx].sum = t[idx].val = v; t[idx].size = 1; return idx; }
void down(int x)
{
if (t[x].rev)
{
if (t[x].ls)copynode(t[x].ls);
if (t[x].rs)copynode(t[x].rs);
swap(t[x].ls, t[x].rs);
rev(t[x].ls); rev(t[x].rs); t[x].rev = 0;
}
}
void up(int x)
{
t[x].sum = t[t[x].ls].sum + t[t[x].rs].sum + t[x].val;
t[x].size = t[t[x].ls].size + t[t[x].rs].size + 1;
}
void split(int x, int& l, int& r, int p)// [1,p) [p,n]
{
if (!x) { l = r = 0; return; }
copynode(x); down(x);
if (t[t[x].ls].size + 1 < p)
{
l = x, split(t[x].rs, t[l].rs, r, p - t[t[x].ls].size - 1), up(l);
}
else
{
r = x, split(t[x].ls, l, t[r].ls, p), up(r);
}
}
int merge(int x, int y)
{
if (!x)return y; if (!y)return x;
if (t[x].k < t[y].k)
{
down(x); t[x].rs = merge(t[x].rs, y); up(x); return x;
}
else
{
down(y); t[y].ls = merge(x, t[y].ls); up(y); return y;
}
}
ll sum(int x, int p)
{
if (p <= 0 || !x)return 0;
if (t[x].size <= p)return t[x].sum;
down(x); const int le = t[t[x].ls].size + 1;
return (le <= p ? t[x].val : 0) + sum(t[x].ls, p) + sum(t[x].rs, p - le);
}
int rt[N];// son down copy
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int n, m, v, opt; int a, b, c; ll last_ans = 0, L, R, p, x;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> v >> opt; rt[i] = rt[v];
if (opt == 1)// add p x
{
cin >> p >> x; p ^= last_ans; x ^= last_ans;
split(rt[i], a, c, p + 1); b = newnode(x);
rt[i] = merge(merge(a, b), c);
}
else if (opt == 2)// del p
{
cin >> p; p ^= last_ans;
split(rt[i], a, b, p + 1);
split(a, a, c, p);
rt[i] = merge(a, b);
}
else if (opt == 3)// rev L R
{
cin >> L >> R; L ^= last_ans; R ^= last_ans;
split(rt[i], b, c, R + 1);
split(b, a, b, L);
rev(b); rt[i] = merge(a, merge(b, c));
}
else // ask L R
{
cin >> L >> R; L ^= last_ans; R ^= last_ans;
cout << (last_ans = sum(rt[i], R) - sum(rt[i], L - 1)) << '\n';
}
}
return 0;
}

浙公网安备 33010602011771号