【模板】普通平衡树(数据加强版)
学习的一种新的平衡树。主要是学到可持久化这个部分,可持久化平衡树似乎用非旋Treap来写会简便一些,就来了。其实这种平衡树很好理解,但由于种种脑残原因我还是写了一个半小时……
这种树思想就是考虑分裂和合并平衡树达到平衡的目的,为了平衡需要用Treap的思想,给每个节点赋值一个优先级,merge的时候按优先级合并就可以保证复杂度。分裂部分也挺好理解,以最常用的按值分裂来说,分裂过程就是首先判断树根在哪棵半树里,然后判断出了树根之后就有一半的节点有了归宿,接下来要做的就是递归下去分裂即可。合并部分写起来很像左偏树,只不过按优先级合并。其它的如插入删除操作都是基于分裂又合并的,复杂度还好,跑起来比我写的Splay慢了一点,但可以接受。
代码:
#include<cstdio>
#include<ctime>
#include<cstdlib>
//#define zczc
using namespace std;
const int N=1100010;
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;
}
int m,n,cnt,root;
#define lc t[x].l
#define rc t[x].r
struct node{
int l,r,data,size,p;
}t[N];
inline int newone(int val){
t[++cnt]=(node){0,0,val,1,rand()};return cnt;
}
inline void pushup(int x){
t[x].size=t[lc].size+t[rc].size+1;
}
inline void split(int x,int val,int &a,int &b){
if(!x){a=b=0;return;}
if(t[x].data<=val){a=x;split(rc,val,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;
if(t[x].p<t[y].p){rc=merge(rc,y);pushup(x);return x;}
else{t[y].l=merge(x,t[y].l);pushup(y);return y;}
}
inline void insert(int val){
int a,b;split(root,val,a,b);
root=merge(merge(a,newone(val)),b);
}
inline void delet(int val){
int a,b,c;
split(root,val,a,c);
split(a,val-1,a,b);
b=merge(t[b].l,t[b].r);
root=merge(merge(a,b),c);
}
int tot;
inline int get(int x,int val){
if(t[lc].size+1==val)return t[x].data;
if(t[lc].size>=val)return get(lc,val);
else return get(rc,val-t[lc].size-1);
}
inline int get_min(int val){
int a,b;split(root,val,a,b);
int re=get(b,1);
root=merge(a,b);return re;
}
inline int get_max(int val){
int a,b;split(root,val-1,a,b);
int re=get(a,t[a].size);
root=merge(a,b);return re;
}
inline int get_rank(int val){
int a,b;split(root,val-1,a,b);
int re=t[a].size+1;
root=merge(a,b);return re;
}
#undef lc
#undef rc
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
srand(time(0));
int op,lan=0,in,ans=0;
read(m);read(n);
for(int i=1;i<=m;i++){read(in);insert(in);}
for(int i=1;i<=n;i++){
read(op);read(in);in^=lan;
if(op==1)insert(in);
else if(op==2)delet(in);
else if(op==3)ans^=(lan=get_rank(in));
else if(op==4)ans^=(lan=get(root,in));
else if(op==5)ans^=(lan=get_max(in));
else if(op==6)ans^=(lan=get_min(in));
}
printf("%d\n",ans);
return 0;
}
一如既往,万事胜意