可持久化文艺平衡树
作者:互联网
Luogu板子题,这玩意儿只能 \(FHQ treap\) 做
(就是好奇为什么空间要开那么大,别的题解都没解释过,我算出来的话是 log 级别的啊...哪位大佬能回答一下啊QWQ)
总体来讲不是非常的 nan ,其实就是江 可持久化线段树 和 FHQ treap 两道紫题并在了一起变成了黑题,假的【雾
但可持久化确实大多是用了可持久化线段树的思路,考虑新建节点,保留历史版本什么的...
于是就这么愉快的 A 了此题...
聊太多了 QWQ ,开始谈题目
首先你得 A 了文艺平衡树(用 FHQ treap A 的) ,FHQ treap 不会的点这里
其次你得学会可持久化的思想,可持久化不会的点这里 (其实是主席树?但是想法类似?)
其实别的都是板子,就是 split 的时候比较特殊罢了,还有下穿标记的时候也是,需要新建节点然后连到父节点那里
//by Judge
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const int N=2e5;
const int M=(N<<7)+3; //注意看
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline ll read(){ ll x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(ll x,char chr='\n'){
if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]=chr;
} int n,op,v,l,r,a,b,c; ll ans;
namespace FHQTreap{ arr rt,pos,siz,fl;
ll w[M],sum[M]; int now,tot,son[M][2];
inline int Rand() { static int seed=703;return seed=int(seed*48271LL%(~0u>>1));}
inline int newnode(ll x=0){return w[++tot]=x,sum[tot]=x,pos[tot]=Rand(),siz[tot]=1,tot;}
inline int copy(int x){ int y=newnode(); //复制节点最好单独来一个小函数...然后里面要 copy 的别忘 copy 全,我被这玩意儿坑了两次
son[y][0]=son[x][0],son[y][1]=son[x][1],siz[y]=siz[x];
w[y]=w[x],sum[y]=sum[x],fl[y]=fl[x]; return y;
}
inline void pushup(int x){
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
sum[x]=sum[son[x][0]]+sum[son[x][1]]+w[x];
}
inline void pushdown(int x){ if(!fl[x]) return; //注意看+1
if(son[x][0]) son[x][0]=copy(son[x][0]);
if(son[x][1]) son[x][1]=copy(son[x][1]);
fl[son[x][0]]^=1,fl[son[x][1]]^=1;
swap(son[x][0],son[x][1]),fl[x]=0;
}
int merge(int x,int y){ if(!x||!y) return x|y; //merge 好像没什么特别的
if(pos[x]<pos[y]) return pushdown(x),son[x][1]=merge(son[x][1],y),pushup(x),x;
else return pushdown(y),son[y][0]=merge(x,son[y][0]),pushup(y),y;
}
void split(int rt,int k,int& x,int& y){ //注意看+1
if(!rt) return x=y=0,void(); pushdown(rt);
if(siz[son[rt][0]]>=k) y=copy(rt),split(son[y][0],k,x,son[y][0]),pushup(y); //这里是copy了之前的节点然后直接拿他做下去了
else x=copy(rt),split(son[x][1],k-siz[son[x][0]]-1,son[x][1],y),pushup(x); //同上
}
} using namespace FHQTreap;
int main(){ //主函数照着题目打就好了
for(n=read();n;--n){ v=read(),op=read();
if(op==1){
l=read()^ans,r=read()^ans,split(rt[v],l,a,b);
rt[++now]=merge(a,merge(newnode(r),b));
} else if(op==2){
l=read()^ans,split(rt[v],l-1,a,b);
split(b,1,b,c),rt[++now]=merge(a,c);
} else if(op==3){ l=read()^ans,r=read()^ans;
split(rt[v],r,a,c),split(a,l-1,a,b);
fl[b]^=1,rt[++now]=merge(a,merge(b,c));
} else if(op==4){ l=read()^ans,r=read()^ans;
split(rt[v],r,a,c),split(a,l-1,a,b);
print(ans=sum[b]),rt[++now]=merge(a,merge(b,c));
}
} return Ot(),0;
}
标签:rt,持久,merge,int,文艺,son,read,split,平衡 来源: https://www.cnblogs.com/Judge/p/10528698.html