可持久化文艺平衡树
(调了我一整个上午,害得我写不了带返回\(split\),罪大恶极)
首先,什么是\(FHQ\)_\(treap\),什么是可持久化,就不用多说了,本文旨在替本人保存代码,本文旨在总结打代码时的坑点。
- 通常来说,可持久化的主要体现——克隆,主要发生在插入、删除、修改等时,但是,由于\(FHQ\)_\(treap\)的实现依赖于\(split\)和\(merge\)操作,所以主要在\(split\)时克隆即可(\(merge\)甚至都不必克隆,引用不会产生新节点,只是合并)
- 此外,在打翻转懒标记时克隆即可
- 带返回\(split\)似乎不能打(我原始版本就打的这个,但是无论怎么都调不对)
#include<iostream>
#include<random>
#define int long long
using namespace std;
const int N=2e5+5;
mt19937_64 Rand(time(0));
struct node{
node *l,*r;
int val,siz,sum,pri,tag;
node(int v): l(nullptr),r(nullptr),val(v),siz(1),sum(v),pri(Rand()),tag(0){}
void pushup(){
siz=1;
sum=val;
if(l!=nullptr){
siz+=l->siz;
sum+=l->sum;
}
if(r!=nullptr){
siz+=r->siz;
sum+=r->sum;
}
}
};
node *rt[N];
struct FHQ_treap{
node *clone(node *u){
if(u==nullptr) return nullptr;
auto tmp=new node(u->val);
tmp->l=u->l;
tmp->r=u->r;
tmp->siz=u->siz;
tmp->pri=u->pri;
tmp->tag=u->tag;
tmp->sum=u->sum;
return tmp;
}
void pushdown(node *u){
if(u==nullptr || !u->tag) return ;
swap(u->l,u->r);
if(u->l!=nullptr){
u->l=clone(u->l);
u->l->tag^=1;
}
if(u->r!=nullptr){
u->r=clone(u->r);
u->r->tag^=1;
}
u->tag=0;
}
int getsiz(node *u){
if(u==nullptr) return 0;
return u->siz;
}
int getsum(node *u){
if(u==nullptr) return 0;
return u->sum;
}
void split(node *u,int k,node *&x,node *&y){
//split实质上是按照一定的条件,将整棵树分为x树和y树
if(u==nullptr){
x=y=nullptr;
return ;
}
pushdown(u);
int lsiz=getsiz(u->l);
if(lsiz+1<=k){
x=clone(u);
// 当前节点u归入x树,并向右子树递归分裂
split(u->r,k-lsiz-1,x->r,y);
x->pushup();
}
else{
y=clone(u);
//同上
split(u->l,k,x,y->l);
y->pushup();
}
}
node *merge(node *u,node *v){
if(u==nullptr) return v;
if(v==nullptr) return u;
pushdown(u);
pushdown(v);
if(u->pri>v->pri){
u->r=merge(u->r,v);
u->pushup();
return u;
}
else{
v->l=merge(u,v->l);
v->pushup();
return v;
}
}
void insert(node *&u,int pos,int val){
node *ltr,*rtr;
split(u,pos,ltr,rtr);
u=merge(merge(ltr,new node(val)),rtr);
}
void erase(node *&u,int pos){
node *ltr,*rtr,*mid;
split(u,pos,mid,rtr);
split(mid,pos-1,ltr,mid);
delete mid;
u=merge(ltr,rtr);
}
void reverse(node *&u,int l,int r){
node *ltr,*rtr,*mid;
split(u,r,mid,rtr);
split(mid,l-1,ltr,mid);
if(mid!=nullptr){
mid=clone(mid);
mid->tag^=1;
}
u=merge(merge(ltr,mid),rtr);
}
int query(node *u,int l,int r){
node *ltr,*rtr,*mid;
split(u,r,mid,rtr);
split(mid,l-1,ltr,mid);
int res=getsum(mid);
u=merge(merge(ltr,mid),rtr);
return res;
}
};
FHQ_treap tr;
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
int n,last=0;
cin>>n;
for(int i=1;i<=n;i++){
int v,opt;
cin>>v>>opt;
rt[i]=rt[v];
if(opt==1){
int p,x;
cin>>p>>x;
p^=last;
x^=last;
tr.insert(rt[i],p,x);
}
if(opt==2){
int p;
cin>>p;
p^=last;
tr.erase(rt[i],p);
}
if(opt==3){
int l,r;
cin>>l>>r;
l^=last;
r^=last;
tr.reverse(rt[i],l,r);
}
if(opt==4){
int l,r;
cin>>l>>r;
l^=last;
r^=last;
last=tr.query(rt[i],l,r);
cout<<last<<'\n';
}
}
}
浙公网安备 33010602011771号