Description
Solution
顾名思义,我们要实现的就是可持久化文艺平衡树,也就是带修的文艺平衡树。
前置知识:文艺平衡树,可持久化平衡树
对于每次修改,我们要新建出被修改的那棵子树,所有的修改及查询操作全都是在要求的版本中进行。
修改之后建出新的版本。
我写的时候直接令 \(rt_i = rt_u\)(\(u\) 是输入的要求在 \(rt_u\) 上面进行操作),然后把 \(rt_i\) 传到函数里即可。
思路大概就是这样吧。
我用 \(fhq-treap\) 实现的。
注意:插入的
split
时,要split(pos)
而不是split(val)
!!!我因为这个卡了一晚上!!!!(可能是我太傻了)
Code
( split
和 pushdown
的过程中要新建节点,各种操作中传入 root
的地址便可以像普通的 \(fhq-treap\) 一样写啦,具体见下面代码)
#include <bits/stdc++.h>
#define ll long long
#define ls(x) t[x].l
#define rs(x) t[x].r
using namespace std;
namespace IO{
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
template <typename T> inline void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
const int N = 2e5 + 10;
int n;
ll lst;
struct fhq_treap{
int val, siz, wei, l, r;
ll sum;
bool rev;
}t[N << 6];
int rt[N], tot;
inline int clone(int y){
int x = ++tot;
return t[x] = t[y], tot;
}
inline void pushup(int x){
t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
t[x].sum = t[ls(x)].sum + t[rs(x)].sum + t[x].val;
}
inline void pushdown(int x){
if(t[x].rev){
swap(ls(x), rs(x));
if(ls(x)) t[x].l = clone(t[x].l), t[t[x].l].rev ^= 1;
if(rs(x)) t[x].r = clone(t[x].r), t[t[x].r].rev ^= 1;
t[x].rev = 0;
}
}
inline void split(int x, int k, int &a, int &b){
if(!x) return a = b = 0, void();
pushdown(x);
if(k >= t[ls(x)].siz + 1){
a = clone(x);
split(rs(x), k - t[ls(x)].siz - 1, rs(a), b);
pushup(a);
}
else{
b = clone(x);
split(ls(x), k, a, ls(b));
pushup(b);
}
}
inline int merge(int x, int y){
if(!x || !y) return x | y;
if(t[x].wei <= t[y].wei){
pushdown(x);
rs(x) = merge(rs(x), y);
return pushup(x), x;
}else{
pushdown(y);
ls(y) = merge(x, ls(y));
return pushup(y), y;
}
}
inline int newnode(int k){
t[++tot].val = k, t[tot].sum = k, t[tot].siz = 1, t[tot].wei = rand();
return tot;
}
inline void insert(int &root, int p, int k){
int a, b;
split(root, p, a, b);
root = merge(merge(a, newnode(k)), b);
}
inline void remove(int &root, int k){
int a, b, c;
split(root, k, a, b);
split(a, k - 1, a, c);
root = merge(a, b);
}
inline void reverse(int &root, int l, int r){
int a, b, c;
split(root, r, a, c);
split(a, l - 1, a, b);
t[b].rev ^= 1;
root = merge(merge(a, b), c);
}
inline ll query(int &root, int l, int r){
int a, b, c;
split(root, r, a, c);
split(a, l - 1, a, b);
ll res = t[b].sum;
root = merge(merge(a, b), c);
return res;
}
int main(){
n = read();
for(int i = 1; i <= n; ++i){
int u = read(), op = read();
rt[i] = rt[u];
if(op == 1){
int p = read() ^ lst, x = read() ^ lst;
insert(rt[i], p, x);
}else if(op == 2) remove(rt[i], read() ^ lst);
else if(op == 3){
int l = read() ^ lst, r = read() ^ lst;
reverse(rt[i], l, r);
}else{
int l = read() ^ lst, r = read() ^ lst;
write(lst = query(rt[i], l, r)), puts("");
}
}
return 0;
}
\[\_EOF\_
\]