\ \ \ \ \ \ \ \, 依然的,只记录模板,不讲原理,关于Splay出门左拐百度。
struct Splay{
#define lson son[0][rt]
#define rson son[1][rt]
int root,cnt;
int son[2][N],sum[N],val[N],size[N],fa[N];
int lazy[N];
}
- r o o t \tt root root :根;
- c n t \tt cnt cnt :下标大小;
- s o n [ 0 / 1 ] [ ] \tt son[0/1][] son[0/1][] :左右儿子;
- s u m [ ] \tt sum[] sum[] :子树大小;
- v a l [ ] \tt val[] val[] :节点权值;
- s i z e [ ] \tt size[] size[] :节点大小;
- f a [ ] \tt fa[] fa[] :节点父亲;
- l a z y [ ] \tt lazy[] lazy[] :下传标记。
void pushup(int rt){
if(!rt)return;
sum[rt]=sum[lson]+sum[rson]+size[rt];
}
- 标记下传 ( p u s h d o w n pushdown pushdown),根据情况会不一样
void pushdown(int rt){
if(!lazy[rt])return;
lazy[lson]^=1;lazy[rson]^=1;
lazy[rt]=0;
swap(lson,rson);
}
- 左旋+右旋 ( r o t a t e rotate rotate)
void rotate(int x){
int y=fa[x];int z=fa[y];
int k=son[1][y]==x;
son[son[1][z]==y][z]=x;
fa[x]=z;
son[k][y]=son[k^1][x];
fa[son[k^1][x]]=y;
son[k^1][x]=y;
fa[y]=x;
pushup(y);pushup(x);
}
- 将 x x x旋转到 g o a l goal goal下 ( s p l a y splay splay)
void splay(int x,int goal){
while(fa[x]!=goal){
int y=fa[x];int z=fa[y];
if(z!=goal)
(son[1][z]==y)^(son[1][y]==x)?rotate(x):rotate(y);
rotate(x);
}
if(goal==0)root=x;
}
int newnode(int f,int v){
int rt=++cnt;
size[rt]=1;sum[rt]=1;val[rt]=v;
fa[rt]=f;lson=rson=0;lazy[rt]=0;
return rt;
}
- 清空节点 ( c l e a n clean clean)
void clean(int rt){
lson=rson=0;fa[rt]=0;
val[rt]=0;sum[rt]=size[rt]=0;
}
- 建立 ( B u i l d Build Build)
void Build(int &rt,int L,int R,int f){
if(L>R)return;
int mid=(L+R)>>1;
rt=newnode(f,a[mid]);
Build(lson,L,mid-1,rt);
Build(rson,mid+1,R,rt);
pushup(rt);
}
- 插入( I n s e r t Insert Insert)
void Insert(int v){
if(!root){root=newnode(0,v);return;}
int now=root,rt=0;
pushdown(now);
while(1){
if(val[now]==v){
++size[now];
pushup(now);pushup(rt);
splay(now,0);
break;
}
rt=now;
val[rt]<v?now=rson:now=lson;
pushdown(now);
if(!now){
now=newnode(rt,v);
val[rt]<v?rson=now:lson=now;
pushup(rt);splay(now,0);
break;
}
}
}
- 删除节点( d e l e t e _ p o s delete\_pos delete_pos)
void delete_pos(int rt){
splay(rt,0);
if(size[rt]>1){--size[rt];return;}
int now;
if(!lson||!rson){
now=rson+lson;pushdown(now);
if(!now){clean(rt);root=0;return;}
clean(rt);root=now;fa[now]=0;
pushup(now);return;
}
now=pre_pos(rt);
pushdown(now);
splay(now,rt);
fa[now]=0;son[1][now]=rson;fa[rson]=now;
root=now;clean(rt);
pushup(rson);pushup(now);
}
- 删除( D e l e t e Delete Delete)
void Delete(int v){
v=QueryRank_pos(v);
pushdown(v);
delete_pos(v);
}
- 删除第k( D e l e t e _ Q u e r y R a n k Delete\_QueryRank Delete_QueryRank)
void Delete_QueryRank(int v){
v=Rank_pos(v);
pushdown(v);
delete_pos(v);
}
- 区间修改(翻转)( r e v s e revse revse)
void revse(int a,int b){
a=find(a);
b=find(b+2);
splay(a,0);splay(b,a);
lazy[son[0][son[1][root]]]^=1;
}
int QueryRank_pos(int x){
int rt=root;
while(1){
pushdown(rt);
if(val[rt]==x){splay(rt,0);return rt;}
if(val[rt]<x)rt=rson;
else if(val[rt]>x)rt=lson;
}
}
- 查找某个排名的节点编号( R a n k _ p o s Rank\_pos Rank_pos)
int Rank_pos(int x){
int rt=root;
while(1){
pushdown(rt);
if(sum[lson]>=x){rt=lson;continue;}
x-=sum[lson];
if(size[rt]>=x){splay(rt,0);return val[rt];}
x-=size[rt];
rt=rson;
}
}
- 查找排名第k的值( Q u e r y R a n k QueryRank QueryRank)
int QueryRank(int x){
int rt=root;
while(1){
pushdown(rt);
if(sum[lson]>=x){rt=lson;continue;}
x-=sum[lson];
if(size[rt]>=x){splay(rt,0);return val[rt];}
x-=size[rt];
rt=rson;
}
}
- 查找某个值的排名( R a n k Rank Rank)
int Rank(int num){
int rt=root,ans=0;
while(1){
pushdown(rt);
if(val[rt]==num){ans=ans+sum[lson]+1;splay(rt,0);return ans;}
if(val[rt]<num)ans+=sum[lson]+size[rt],rt=rson;
else if(val[rt]>num)rt=lson;
}
}
- 集合内前驱的节点编号( p r e _ p o s pre\_pos pre_pos)
int pre_pos(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[0][x]))return val[x];
while(rson)pushdown(rt),rt=rson;
return rt;
}
- 集合内后继的节点编号( n e x _ p o s nex\_pos nex_pos)
int nex_pos(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[1][x]))return val[x];
while(lson)pushdown(rt),rt=lson;
return rt;
}
- 集合内前驱的值( p r e pre pre)
int pre(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[0][x]))return val[x];
while(rson)pushdown(rt),rt=rson;
return val[rt];
}
- 集合内后继的值( n e x nex nex)
int nex(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[1][x]))return val[x];
while(lson)pushdown(rt),rt=lson;
return val[rt];
}
- 前驱( N u m p r e Numpre Numpre)
int Numpre(int x){
Insert(x);
int y=x;x=QueryRank_pos(x);
int ls=pre(x);
Delete(y);
return ls;
}
- 后继( N u m n e x Numnex Numnex)
int Numnex(int x){
Insert(x);
int y=x;x=QueryRank_pos(x);
int ls=nex(x);
Delete(y);
return ls;
}
- 查找某个值的节点编号( f i n d find find),不改变结构
int find(int k){
int rt=root;
while(1){
pushdown(rt);
if(sum[lson]>=k)rt=lson;
else if(sum[lson]+1==k)return rt;
else k-=sum[lson]+1,rt=rson;
}
}
const int N=1e5+10;
int a[N],n,m;
struct Splay{
#define lson son[0][rt]
#define rson son[1][rt]
int root,cnt;
int son[2][N],sum[N],val[N],size[N],fa[N];
bool lazy[N];
void pushdown(int rt){
if(!lazy[rt])return;
lazy[lson]^=1;lazy[rson]^=1;
lazy[rt]=0;
swap(lson,rson);
}
void pushup(int rt){
if(!rt)return;
sum[rt]=sum[lson]+sum[rson]+size[rt];
}
void rotate(int x){
int y=fa[x];int z=fa[y];
int k=son[1][y]==x;
son[son[1][z]==y][z]=x;
fa[x]=z;
son[k][y]=son[k^1][x];
fa[son[k^1][x]]=y;
son[k^1][x]=y;
fa[y]=x;
pushup(y);pushup(x);
}
void splay(int x,int goal){
while(fa[x]!=goal){
int y=fa[x];int z=fa[y];
if(z!=goal)
(son[1][z]==y)^(son[1][y]==x)?rotate(x):rotate(y);
rotate(x);
}
if(goal==0)root=x;
}
int newnode(int f,int v){
int rt=++cnt;
size[rt]=1;sum[rt]=1;val[rt]=v;
fa[rt]=f;lson=rson=0;lazy[rt]=0;
return rt;
}
void clean(int rt){
lson=rson=0;fa[rt]=0;
val[rt]=0;sum[rt]=size[rt]=0;
}
void Build(int &rt,int L,int R,int f){
if(L>R)return;
int mid=(L+R)>>1;
rt=newnode(f,a[mid]);
Build(lson,L,mid-1,rt);
Build(rson,mid+1,R,rt);
pushup(rt);
}
void Insert(int v){
if(!root){root=newnode(0,v);return;}
int now=root,rt=0;
pushdown(now);
while(1){
if(val[now]==v){
++size[now];
pushup(now);pushup(rt);
splay(now,0);
break;
}
rt=now;
val[rt]<v?now=rson:now=lson;
pushdown(now);
if(!now){
now=newnode(rt,v);
val[rt]<v?rson=now:lson=now;
pushup(rt);splay(now,0);
break;
}
}
}
int QueryRank_pos(int x){
int rt=root;
while(1){
pushdown(rt);
if(val[rt]==x){splay(rt,0);return rt;}
if(val[rt]<x)rt=rson;
else if(val[rt]>x)rt=lson;
}
}
int Rank_pos(int x){
int rt=root;
while(1){
pushdown(rt);
if(sum[lson]>=x){rt=lson;continue;}
x-=sum[lson];
if(size[rt]>=x){splay(rt,0);return val[rt];}
x-=size[rt];
rt=rson;
}
}
int QueryRank(int x){
int rt=root;
while(1){
pushdown(rt);
if(sum[lson]>=x){rt=lson;continue;}
x-=sum[lson];
if(size[rt]>=x){splay(rt,0);return val[rt];}
x-=size[rt];
rt=rson;
}
}
int Rank(int num){
int rt=root,ans=0;
while(1){
pushdown(rt);
if(val[rt]==num){ans=ans+sum[lson]+1;splay(rt,0);return ans;}
if(val[rt]<num)ans+=sum[lson]+size[rt],rt=rson;
else if(val[rt]>num)rt=lson;
}
}
int pre_pos(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[0][x]))return val[x];
while(rson)pushdown(rt),rt=rson;
return rt;
}
int nex_pos(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[1][x]))return val[x];
while(lson)pushdown(rt),rt=lson;
return rt;
}
int pre(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[0][x]))return val[x];
while(rson)pushdown(rt),rt=rson;
return val[rt];
}
int nex(int x){
splay(x,0);int rt;
pushdown(x);
if(!(rt=son[1][x]))return val[x];
while(lson)pushdown(rt),rt=lson;
return val[rt];
}
void delete_pos(int rt){
splay(rt,0);
if(size[rt]>1){--size[rt];return;}
int now;
if(!lson||!rson){
now=rson+lson;pushdown(now);
if(!now){clean(rt);root=0;return;}
clean(rt);root=now;fa[now]=0;
pushup(now);return;
}
now=pre_pos(rt);
pushdown(now);
splay(now,rt);
fa[now]=0;son[1][now]=rson;fa[rson]=now;
root=now;clean(rt);
pushup(rson);pushup(now);
}
void Delete(int v){
v=QueryRank_pos(v);
pushdown(v);
delete_pos(v);
}
void Delete_QueryRank(int v){
v=Rank_pos(v);
pushdown(v);
delete_pos(v);
}
int Numpre(int x){
Insert(x);
int y=x;x=QueryRank_pos(x);
int ls=pre(x);
Delete(y);
return ls;
}
int Numnex(int x){
Insert(x);
int y=x;x=QueryRank_pos(x);
int ls=nex(x);
Delete(y);
return ls;
}
int find(int k){
int rt=root;
while(1){
pushdown(rt);
if(sum[lson]>=k)rt=lson;
else if(sum[lson]+1==k)return rt;
else k-=sum[lson]+1,rt=rson;
}
}
void revse(int a,int b){
a=find(a);
b=find(b+2);
splay(a,0);splay(b,a);
lazy[son[0][son[1][root]]]^=1;
}
}Spl;
-
两个模板题:
- P3369 【模板】普通平衡树
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
using namespace std;
const int inf=0x7fffffff;
const double eps=1e-10;
const double pi=acos(-1.0);
//char buf[1<<15],*S=buf,*T=buf;
//char getch(){return S==T&&(T=(S=buf)+fread(buf,1,1<<15,stdin),S==T)?0:*S++;}
inline int read(){
int x=0,f=1;char ch;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();}
if(f)return x;else return -x;
}
const int N=1e5+10;
int a[N],n,m;
struct Splay{
}Spl;
int main()
{
int n=read();
while(n--){
int opt=read(),x=read();
if(opt==1){Spl.Insert(x);continue;}
if(opt==2){Spl.Delete(x);continue;}
if(opt==3){printf("%d\n",Spl.Rank(x));continue;}
if(opt==4){printf("%d\n",Spl.QueryRank(x));continue;}
if(opt==5){printf("%d\n",Spl.Numpre(x));continue;}
if(opt==6){printf("%d\n",Spl.Numnex(x));continue;}
}
return 0;
}
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
using namespace std;
const int inf=0x7fffffff;
const double eps=1e-10;
const double pi=acos(-1.0);
//char buf[1<<15],*S=buf,*T=buf;
//char getch(){return S==T&&(T=(S=buf)+fread(buf,1,1<<15,stdin),S==T)?0:*S++;}
inline int read(){
int x=0,f=1;char ch;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();}
if(f)return x;else return -x;
}
const int N=1e5+10;
int a[N],n,m;
struct Splay{
}Spl;
void write(int rt){
Spl.pushdown(rt);
if(Spl.lson)write(Spl.lson);
if(Spl.val[rt]>1&&Spl.val[rt]<n+2)
printf("%d ",Spl.val[rt]-1);
if(Spl.rson)write(Spl.rson);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n+2;i++)a[i]=i;
Spl.Build(Spl.root,1,n+2,0);
while(m--){
int l=read(),r=read();
Spl.revse(l,r);
}
write(Spl.root);
printf("\n");
return 0;
}