版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/86483031
传送门
解析:
不会有人真的试图去可持久化Splay吧。。。
你仔细研究一下就会发现Splay最坏情况下会把树中所有节点的父子关系全部打乱。。。两三次操作就新建 个节点,于是你就RE或者MLE了。
当然你可以试一试朝鲜树可持久化,不过复杂度不够优秀。
于是这里请出优秀的FHQ_treap。
不持久化的话都是常规操作吧, 废话
可持久化还是比较简单的,我们只需要在下放标记的时候新建一波节点split的时候新建一波节点。
merge就不用新建了,因为merge出的链上都是split的链出来的节点,所以我们只需要在split的时候新建就行了。
当然空间常数十分不优秀就对了(不然你可以写 的朝鲜树(而且还不兹磁区间操作))。(逃
代码;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<18|1;
char buf[Rlen],*p1,*p2;
char obuf[Rlen],*p3=obuf;
char ch[23];
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline void put_char(char c){
using namespace IOONLY;
*p3++=c;
if(p3==obuf+Rlen)fwrite(obuf,1,Rlen,stdout),p3=obuf;
}
inline void FLUSH(){
using namespace IOONLY;
fwrite(obuf,1,p3-obuf,stdout),p3=obuf;
}
inline int getint(){
re int num;
re char c;
re bool f=0;
while(!isdigit(c=gc()))if(c=='-')f=1;num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
inline void outint(ll a){
using namespace IOONLY;
if(a==0)pc('0');
if(a<0)pc('-'),a=-a;
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
}
using namespace IO;
cs int N=200005,B=120;
ll lasans;
namespace FHQ_treap{
namespace Vars{
int son[N*B][2];
int siz[N*B];
int val[N*B];
ll sum[N*B];
int pri[N*B];
bool rev[N*B];
int tot;
}
inline int newnode(int _val){
using namespace Vars;
int now=++tot;
siz[now]=1;
son[now][0]=son[now][1]=0;
val[now]=_val;
pri[now]=rand();
rev[now]=0;
sum[now]=_val;
return now;
}
inline int copy_node(int _c){
using namespace Vars;
int now=++tot;
siz[now]=siz[_c];
son[now][0]=son[_c][0];
son[now][1]=son[_c][1];
val[now]=val[_c];
pri[now]=pri[_c];
rev[now]=rev[_c];
sum[now]=sum[_c];
return now;
}
inline void pushup(int now){
using namespace Vars;
siz[now]=siz[son[now][0]]+siz[son[now][1]]+1;
sum[now]=sum[son[now][0]]+sum[son[now][1]]+val[now];
}
inline void pushdown(int now){
using namespace Vars;
if(rev[now]){
if(son[now][0])son[now][0]=copy_node(son[now][0]);
if(son[now][1])son[now][1]=copy_node(son[now][1]);
swap(son[now][0],son[now][1]);
if(son[now][0])rev[son[now][0]]^=1;
if(son[now][1])rev[son[now][1]]^=1;
rev[now]=0;
}
}
pair<int,int> split_siz(int now,cs int &key){
using namespace Vars;
if(!now)return make_pair(0,0);
pair<int,int> res;
pushdown(now);
now=copy_node(now);
if(key<siz[son[now][0]]+1){
res=split_siz(son[now][0],key);
son[now][0]=res.second;
res.second=now;
}
else {
res=split_siz(son[now][1],key-siz[son[now][0]]-1);
son[now][1]=res.first;
res.first=now;
}
pushup(now);
return res;
}
int merge(int lc,int rc){
using namespace Vars;
if(!lc||!rc)return lc+rc;
pushdown(lc);
pushdown(rc);
if(pri[lc]>pri[rc]){
son[lc][1]=merge(son[lc][1],rc);
pushup(lc);
return lc;
}
else {
son[rc][0]=merge(lc,son[rc][0]);
pushup(rc);
return rc;
}
}
inline int Insert(int now,int pos,int _val){
using namespace Vars;
pair<int,int> res=split_siz(now,pos);
return merge(merge(res.first,newnode(_val)),res.second);
}
inline int Del(int now,int pos){
using namespace Vars;
pair<int,int> res1=split_siz(now,pos-1);
pair<int,int> res2=split_siz(res1.second,1);
return merge(res1.first,res2.second);
}
inline int rev_range(int now,int l,int r){
using namespace Vars;
pair<int,int> res1=split_siz(now,r);
pair<int,int> res2=split_siz(res1.first,l-1);
rev[res2.second]^=1;
return merge(merge(res2.first,res2.second),res1.second);
}
inline int query_sum(int now,int l,int r){
using namespace Vars;
pair<int,int> res1=split_siz(now,r);
pair<int,int> res2=split_siz(res1.first,l-1);
outint(lasans=sum[res2.second]);pc('\n');
return merge(merge(res2.first,res2.second),res1.second);
}
}
using namespace FHQ_treap;
int n;
int rt[N];
signed main(){
n=getint();
for(int re i=1;i<=n;++i){
int v=getint(),op=getint();
switch(op){
case 1:{
int pos=getint()^lasans,_val=getint()^lasans;
rt[i]=Insert(rt[v],pos,_val);
break;
}
case 2:{
int pos=getint()^lasans;
rt[i]=Del(rt[v],pos);
break;
}
case 3:{
int l=getint()^lasans,r=getint()^lasans;
rt[i]=rev_range(rt[v],l,r);
break;
}
case 4:{
int l=getint()^lasans,r=getint()^lasans;
rt[i]=query_sum(rt[v],l,r);
break;
}
}
}
FLUSH();
return 0;
}