【模板】可持久化文艺平衡树
模板。其实思想和普通的用无旋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;
}
一如既往,万事胜意