题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1861
发现自己想splay的时候总是纠结那个点权是什么,因为splay原本是二分查找树...
但其实splay已经不是维护点权大小顺序的,它的最大作用就在于无论怎样旋转都保持着中序遍历这个相对位置不变;
所以很对应这道题,用splay进行各种操作的同时书的摆放顺序是不变的;
假设出一个‘1’点、一个‘n+1’点方便操作,所以整体+1;
这个建树的方法不错呢。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=80005,inf=0x3f3f3f3f; int n,m,rt,a[maxn],pos[maxn],v[maxn],c[maxn][3],siz[maxn],fa[maxn]; void pushup(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;} void build(int l,int r,int f) { if(l>r)return; if(l==r) { v[l]=a[l];siz[l]=1;fa[l]=f; // if(l<f)c[f][0]=l;else c[f][1]=l; c[f][(l>f)]=l; return; } int mid=((l+r)>>1); build(l,mid-1,mid);build(mid+1,r,mid); v[mid]=a[mid];fa[mid]=f; // if(mid<f)c[f][0]=mid;else c[f][1]=mid; c[f][(mid>f)]=mid; pushup(mid); } void rotate(int x,int &k) { int y=fa[x],z=fa[y]; int d=(c[y][1]==x); if(y==k)k=x; else c[z][(c[z][1]==y)]=x; fa[x]=z;fa[y]=x;fa[c[x][d^1]]=y; c[y][d]=c[x][d^1];c[x][d^1]=y; pushup(y);pushup(x); } void splay(int x,int &k) { while(x!=k) { int y=fa[x],z=fa[y]; if(y!=k) { if((c[y][0]==x)^(c[z][0]==y))rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int x,int rank) { int l=c[x][0],r=c[x][1]; if(rank==siz[l]+1)return x; else if(rank<=siz[l])return find(l,rank); else return find(r,rank-siz[l]-1); } void del(int k) { int x=find(rt,k-1),y=find(rt,k+1); splay(x,rt);splay(y,c[x][1]); int z=c[y][0];c[y][0]=0;siz[z]=0;fa[z]=0; pushup(y);pushup(x); } void move(int k,int val) { int x,y,z=pos[k],rank; splay(z,rt);rank=siz[c[z][0]]+1; del(rank); if(val==-inf)x=find(rt,1),y=find(rt,2); else if(val==inf)x=find(rt,n),y=find(rt,n+1);//else if而非if!!! //del后有n-1本书 else x=find(rt,rank+val-1),y=find(rt,rank+val); splay(x,rt);splay(y,c[x][1]); c[y][0]=z;siz[z]=1;fa[z]=y; pushup(y);pushup(x); } int main() { scanf("%d%d",&n,&m); for(int i=2;i<=n+1;i++) scanf("%d",&a[i]),pos[a[i]]=i; build(1,n+2,0);rt=(n+3)/2;//+'1' char ch[10]; for(int i=1,x,T;i<=m;i++) { scanf("%s",&ch);scanf("%d",&x); if(ch[0]=='T')move(x,-inf);//top if(ch[0]=='B')move(x,inf);//bottom if(ch[0]=='I')scanf("%d",&T),move(x,T); if(ch[0]=='A')splay(pos[x],rt),printf("%d\n",siz[c[pos[x]][0]]-1);//'1' if(ch[0]=='Q')printf("%d\n",v[find(rt,x+1)]);//'1' } return 0; }