Splay学习
基本操作:
void rotate(int x){ int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x); tr[y].son[c^1]=tr[x].son[c]; tr[tr[x].son[c]].fa=y; tr[x].son[c]=y;tr[y].fa=x;tr[x].fa=z; if(z)tr[z].son[tr[z].son[1]==y]=x; pushup(y);pushup(x); return ; } void splay(int x,int goal){ while(tr[x].fa!=goal){ int y=tr[x].fa,z=tr[y].fa; if(z!=goal)(tr[z].son[0]==y)^(tr[y].son[0]==x)?rotate(x):rotate(y); rotate(x); } if(!goal)root=x; }
一些小细节:
- splay双旋
- 经常设置虚点,使得完成某些包含开头或结尾的操作
- splay tree是一种二叉搜索树,它的左儿子的权值<自己的权值<右儿子的权值,节点的权值不仅可以代表数值,也可以代表序列的顺序
插入、删除、查数x排名、查排名为x的数,前驱后继
//luogu【模板】普通平衡树 #include<functional> #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=2000000+101; int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } int n,root,tot; struct wzq{int son[2],v,fa,cnt,sz;}tr[maxn]; void pushup(int x){tr[x].sz=tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz+tr[x].cnt;} void rotate(int x){ int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x); tr[y].son[c^1]=tr[x].son[c]; tr[tr[x].son[c]].fa=y;tr[x].son[c]=y; tr[y].fa=x;tr[x].fa=z; if(z)tr[z].son[tr[z].son[1]==y]=x; pushup(y);pushup(x); return ; } void splay(int x,int goal){ while(tr[x].fa!=goal){ int y=tr[x].fa,z=tr[y].fa; if(z!=goal)(tr[z].son[0]==y)^(tr[y].son[0]==x)?rotate(x):rotate(y); rotate(x); } if(!goal)root=x; } void insert(int val){ int x=root,f=0; while(x && tr[x].v!=val){f=x;x=tr[x].son[tr[x].v<val];} if(x){tr[x].cnt++;splay(x,0);return ;} x=++tot; if(f)tr[f].son[tr[f].v<val]=x; tr[x].son[0]=tr[x].son[1]=0; tr[x].v=val;tr[x].fa=f;tr[x].cnt=tr[x].sz=1; splay(x,0);return ; } void Find(int val){ int x=root; if(!x)return ; while(1){ if(tr[x].v==val){splay(x,0);return ;} if(tr[x].son[tr[x].v<val])x=tr[x].son[tr[x].v<val]; else {splay(x,0);return ;} } } int Next(int val,int f){ //0前 1后 Find(val);int x=root; if((tr[x].v<val && !f) || (tr[x].v>val && f))return x; x=tr[x].son[f]; while(tr[x].son[f^1])x=tr[x].son[f^1]; return x; } void delet(int val){ int qian=Next(val,0),hou=Next(val,1); splay(qian,0);splay(hou,qian); int x=tr[hou].son[0]; if(tr[x].cnt>1){ tr[x].cnt--; splay(x,0); } else tr[hou].son[0]=0; return ; } int Kth(int k){ int x=root; while(1){ int t=tr[x].son[0]; if(tr[t].sz+tr[x].cnt<k){ k=k-tr[t].sz-tr[x].cnt; x=tr[x].son[1]; } else { if(tr[t].sz<k)return tr[x].v; x=t; } } } int main(){ insert(2147483647);insert(-2147483647); n=read();int num=0; for(int i=1;i<=n;i++){ int opt=read(),x=read(); if(opt==1)insert(x); if(opt==2)delet(x); if(opt==3){Find(x);printf("%d\n",tr[tr[root].son[0]].sz);} if(opt==4){printf("%d\n",Kth(x+1));} if(opt==5){printf("%d\n",tr[Next(x,0)].v);} if(opt==6){printf("%d\n",tr[Next(x,1)].v);} } return 0; }
区间删除、插入、翻转
//HDU3487 #include<functional> #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=500000+101; const int MOD=998244353; const int inf=2147483647; int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } int n,m,tot,root,sum; struct wzq{int v,son[2],cnt,sz,fa,rev;}tr[maxn]; void update(int x){tr[x].sz=tr[x].cnt+tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz;} void pushdown(int x){ if(tr[x].rev){ tr[x].rev^=1; swap(tr[x].son[1],tr[x].son[0]); tr[tr[x].son[1]].rev^=1; tr[tr[x].son[0]].rev^=1; } return ; } void rotate(int x){ pushdown(x); int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x); tr[y].son[c^1]=tr[x].son[c]; tr[y].fa=x;tr[tr[x].son[c]].fa=y;tr[x].fa=z; tr[x].son[c]=y; if(z)tr[z].son[tr[z].son[1]==y]=x; update(y);update(x); } void splay(int x,int goal){ while(tr[x].fa!=goal){ int y=tr[x].fa,z=tr[y].fa; if(z!=goal)(tr[y].son[0]==x)^(tr[z].son[0]==y)?rotate(x):rotate(y); rotate(x); } if(!goal)root=x; } int Kth(int val){ int x=root; while(1){ pushdown(x); int left=tr[x].son[0],right=tr[x].son[1]; if(val>tr[left].sz+tr[x].cnt)val-=tr[left].sz+tr[x].cnt,x=tr[x].son[1]; else { if(val<=tr[left].sz)x=left; else return x; } } } int New(int f,int val){ int x=++tot;tr[x].v=val; tr[x].fa=f;tr[x].cnt=tr[x].sz=1; tr[x].son[0]=tr[x].son[1]=tr[x].rev=0; return x; } void build(int f,int l,int r,int &t){ if(l>r)return; int mid=(l+r)>>1;t=New(f,mid); build(t,l,mid-1,tr[t].son[0]); build(t,mid+1,r,tr[t].son[1]); update(t);return ; } void init(){ sum=tot=root=0;tr[0].son[0]=tr[0].son[1]=tr[0].sz=0; root=New(0,-inf);tr[root].son[1]=New(root,inf); tr[root].sz=2; build(tr[root].son[1],1,n,tr[tr[root].son[1]].son[0]); update(tr[root].son[1]);update(root); } void prin(int x){ pushdown(x); if(!x)return ; prin(tr[x].son[0]); if(tr[x].v!=inf && tr[x].v!=-inf){ sum++; if(sum!=n)printf("%d ",tr[x].v); else printf("%d\n",tr[x].v); } prin(tr[x].son[1]); } int main(){ while(1){ n=read();m=read();if(n<0 && m<0)break; init(); for(int i=1;i<=m;i++){ char ch[10];cin>>ch;int x,y,z; if(ch[0]=='C'){ x=read()+1;y=read()+1;z=read()+1; int xx=Kth(x-1),yy=Kth(y+1); splay(xx,0);splay(yy,xx); int las=tr[yy].son[0]; tr[yy].son[0]=0;update(yy);update(xx); xx=Kth(z),yy=Kth(z+1); splay(xx,0);splay(yy,xx); tr[yy].son[0]=las;tr[las].fa=yy; update(yy);update(xx); } else { x=read()+1;y=read()+1; splay(Kth(x-1),0);splay(Kth(y+1),Kth(x-1)); tr[tr[tr[root].son[1]].son[0]].rev^=1; } } prin(root); } return 0; }
splay区间操作大全
插入、删除、区间查询、区间翻转、区间旋转、区间修改
//poj3580 #include<functional> #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<cstdio> #include<cmath> #include<queue> #define ll long long using namespace std; const int maxn=100000+101; const int MOD=998244353; const int inf=2147483647; int read(){ int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } int n,m,a[maxn]; int root,tot; struct wzq{int v,son[2],sz,fa,cnt,lz,minv,rev;}tr[maxn]; void update(int x){ tr[x].minv=tr[x].v; tr[x].sz=tr[x].cnt+tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz; if(tr[x].son[0])tr[x].minv=min(tr[x].minv,tr[tr[x].son[0]].minv); if(tr[x].son[1])tr[x].minv=min(tr[x].minv,tr[tr[x].son[1]].minv); } void pushdown(int x){ if(tr[x].rev){ tr[x].rev=0; swap(tr[x].son[0],tr[x].son[1]); tr[tr[x].son[0]].rev^=1; tr[tr[x].son[1]].rev^=1; } if(tr[x].lz){ tr[tr[x].son[0]].lz+=tr[x].lz;tr[tr[x].son[1]].lz+=tr[x].lz; tr[tr[x].son[0]].minv+=tr[x].lz;tr[tr[x].son[1]].minv+=tr[x].lz; tr[tr[x].son[0]].v+=tr[x].lz;tr[tr[x].son[1]].v+=tr[x].lz; tr[x].lz=0; } return ; } void rotate(int x){ pushdown(x); int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x); tr[y].son[c^1]=tr[x].son[c]; tr[y].fa=x;tr[tr[x].son[c]].fa=y;tr[x].fa=z; tr[x].son[c]=y; if(z)tr[z].son[tr[z].son[1]==y]=x; update(y);update(x); } void splay(int x,int goal){ while(tr[x].fa!=goal){ int y=tr[x].fa,z=tr[y].fa; if(z!=goal)(tr[y].son[0]==x)^(tr[z].son[0]==y)?rotate(x):rotate(y); rotate(x); } if(!goal)root=x; } int New(int f,int val){ int x=++tot; tr[x].fa=f;tr[x].sz=tr[x].cnt=1;tr[x].v=tr[x].minv=val; tr[x].lz=tr[x].rev=tr[x].son[0]=tr[x].son[1]=0; return x; } void build(int f,int l,int r,int &t){ if(l>r)return ; int mid=(l+r)>>1; t=New(f,a[mid]); build(t,l,mid-1,tr[t].son[0]); build(t,mid+1,r,tr[t].son[1]); update(t); } void init(){ root=New(0,-inf);tr[root].son[1]=New(root,inf); build(tr[root].son[1],1,n,tr[tr[root].son[1]].son[0]); update(tr[root].son[1]);update(root); } int Kth(int val){ int x=root; while(1){ pushdown(x); int left=tr[x].son[0],right=tr[x].son[1]; if(val>tr[left].sz+tr[x].cnt)val-=tr[left].sz+tr[x].cnt,x=tr[x].son[1]; else { if(val<=tr[left].sz)x=left; else return x; } } } int main(){ n=read();for(int i=1;i<=n;i++)a[i]=read(); m=read();init(); for(int i=1;i<=m;i++){ char ch[10];cin>>ch;int x,y,d; if(ch[0]=='A'){ x=read()+1;y=read()+1;d=read(); int xx=Kth(x-1),yy=Kth(y+1); splay(xx,0);splay(yy,xx); tr[tr[yy].son[0]].lz+=d; tr[tr[yy].son[0]].minv+=d; tr[tr[yy].son[0]].v+=d; update(yy);update(xx); } else if(ch[0]=='R' && ch[3]=='E'){ x=read()+1,y=read()+1; int xx=Kth(x-1),yy=Kth(y+1); splay(xx,0);splay(yy,xx); tr[tr[yy].son[0]].rev^=1; } else if(ch[0]=='R' && ch[3]=='O'){ x=read()+1,y=read()+1,d=read();d=d%(y-x+1); if(d==0)continue; int x1=Kth(y-d),y1=Kth(y+1); splay(x1,0);splay(y1,x1); int tmp=tr[y1].son[0];tr[y1].son[0]=0;update(y1);update(x1); int xx=Kth(x-1),yy=Kth(x); splay(xx,0);splay(yy,xx); tr[yy].son[0]=tmp;tr[tmp].fa=yy;update(yy);update(xx); } else if(ch[0]=='D'){ x=read()+1;int xx=Kth(x-1),yy=Kth(x+1); splay(xx,0);splay(yy,xx); tr[yy].son[0]=0;update(yy);update(xx); } else if(ch[0]=='M'){ x=read()+1,y=read()+1; int xx=Kth(x-1),yy=Kth(y+1); splay(xx,0);splay(yy,xx); printf("%d\n",tr[tr[yy].son[0]].minv); } else if(ch[0]=='I'){ x=read()+1;y=read(); int xx=Kth(x),yy=Kth(x+1); splay(xx,0);splay(yy,xx); int kk=New(yy,y); tr[yy].son[0]=kk;update(yy);update(xx); } } return 0; }