【模板】可持久化文艺平衡树

link

模板。其实思想和普通的用无旋Treap实现可持久化平衡树一样,都是考虑新建状态可能会带来什么影响。无旋Treap的基础就是分裂,可以想见它可以实现和Splay类似的提取区间操作(而且貌似更加直观),然后就是可持久化地进行split和merge。该打标计就打标计,该下放就下放(split和merge都是一路下放),需要注意的是在pushdown函数中,如果要交换左右孩子的话需要新建节点,毕竟可持久化的要求就是咱不能影响过去的事情……

空间好评,整整一个G。还有就是数组开得有点骇人听闻,1e8的long long,恐怕OI生涯里这种题也是不多见的。还有就是要开long long,虽然鬼知道涉及负数的异或运算出题人是怎么想的。

code

#include<cstdio>
#include<cstdlib>
#include<ctime>
//#define zczc
#define int long long
using namespace std;
const int N=200010;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}
inline void swap(int &s1,int &s2){
	int s3=s1;s1=s2;s2=s3;return;
}

#define lc t[x].l
#define rc t[x].r
struct node{
	int l,r,data,sum,size,p;bool lazy;
}t[N<<7];
int ti,cnt,root[N];
inline int newone(int val){
	t[++cnt]=(node){0,0,val,val,1,rand(),false};
	return cnt;
}
inline int copy(int x){
	t[++cnt]=t[x];return cnt;
}
inline void pushdown(int x){
	if(t[x].lazy==false)return;
	t[x].lazy=false;
	if(lc)lc=copy(lc);
	if(rc)rc=copy(rc);
	swap(lc,rc);
	if(lc)t[lc].lazy^=1;
	if(rc)t[rc].lazy^=1;
}
inline void pushup(int x){
	t[x].size=t[lc].size+t[rc].size+1;
	t[x].sum=t[lc].sum+t[rc].sum+t[x].data;
}
inline void split(int x,int val,int &a,int &b){
	if(!x){a=b=0;return;}pushdown(x);
	int y=x;x=++cnt;t[x]=t[y];
	if(t[lc].size+1<=val){a=x;split(rc,val-t[lc].size-1,rc,b);}
	else{b=x;split(lc,val,a,lc);}pushup(x);
}
inline int merge(int x,int y){
	if(!x||!y)return x+y;int s=++cnt;
	pushdown(x);pushdown(y);
	if(t[x].p<t[y].p){t[s]=t[x];t[s].r=merge(t[s].r,y);}
	else{t[s]=t[y];t[s].l=merge(x,t[s].l);}
	pushup(s);return s;
}
inline void insert(int h,int pl,int val){
	int a,b;split(root[h],pl,a,b);
	root[ti]=merge(merge(a,newone(val)),b);
}
inline void del(int h,int pl){
	int a,b,c;split(root[h],pl,a,c);
	split(a,pl-1,a,b);
	root[ti]=merge(a,c);
}
inline int work(int h,int l,int r){
	int a,b,c;split(root[h],r,a,c);
	split(a,l-1,a,b);root[ti]=root[h];
	return t[b].sum;
}
inline void change(int h,int l,int r){
	int a,b,c;
	split(root[h],r,a,c);
	split(a,l-1,a,b);
	t[b].lazy^=1;
	root[ti]=merge(merge(a,b),c);
}
#undef lc
#undef rc

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	srand(time(0));
	
	int m,h,op,l,r,lan=0;
	read(m);
	for(ti=1;ti<=m;ti++){
		read(h);read(op);read(l);
		if(op^2)read(r);
		l^=lan,r^=lan;
		switch(op){
			case 1:insert(h,l,r);break;
			case 2:del(h,l);break;
			case 3:change(h,l,r);break;
			case 4:printf("%lld\n",lan=work(h,l,r));break;
		}
	}
	
	return 0;
}
posted @ 2022-04-09 12:41  Feyn618  阅读(72)  评论(0编辑  收藏  举报