splay的另一种应用,维护序列,不再按照权值建平衡树,而是按照下标建平衡树,然后维护一些东西。
题目大意:
1、把编号为S的书放到最上面
2、把编号为S的书放到最下面
3、把编号为S的书前移、后移或者不动
4、询问编号为S的书上面有多少本书
5、询问第S本书的编号
很朴素的平衡树,不需要维护任何东西,直接模拟就好。
记录一下编号为S的书对应的splay上的节点。
1、2、3 删掉这本书,新建一个节点,插入对应位置
4、把对应节点旋转到根,求左子树大小
5、从根开始查找第S小的节点。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #define inf 1000000000 #define maxn 160010 using namespace std; int ch[maxn][2],fa[maxn],size[maxn],w[maxn]; int pos[maxn]; int tot,n,m,T,root; char s[110]; int dir(int x) { return x==ch[fa[x]][1]; } void update(int x) { size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void rotate(int x) { int y,z,a,b,c; y=fa[x];z=fa[y];b=dir(x);a=ch[x][!b]; if (z==0) root=x; else { c=dir(y);ch[z][c]=x; } fa[x]=z;fa[y]=x;ch[x][!b]=y;ch[y][b]=a; if (a) fa[a]=y; update(y);update(x); } void splay(int x,int i) { int y,z,b,c; while (fa[x]!=i) { y=fa[x];z=fa[y]; if (z==i) rotate(x); else { b=dir(x);c=dir(y); if (b^c) { rotate(x);rotate(x); } else { rotate(y);rotate(x); } } } } int find_pre(int x,int d) { if (!x) return x; if (w[x]>=d) return find_pre(ch[x][0],d); else { int y=find_pre(ch[x][1],d); if (y) return y; else return x; } } int find_k(int x,int k) { if (size[ch[x][0]]==k-1) return x; if (size[ch[x][0]]>k-1) return find_k(ch[x][0],k); else return find_k(ch[x][1],k-size[ch[x][0]]-1); } void insert(int k,int d) { int x=find_k(root,k);splay(x,0); int y=find_k(ch[x][1],1);splay(y,x); tot++; fa[tot]=y;size[tot]=1;w[tot]=d;ch[y][0]=tot; pos[d]=tot; update(y);update(x); } int query(int x) { splay(x,0); return size[ch[x][0]]; } void del(int k) { int x=find_k(root,query(k));splay(x,0); int y=find_k(ch[x][1],2);splay(y,x); size[ch[y][0]]=0;fa[ch[y][0]]=0;ch[y][0]=0; update(y);update(x); } int main() { size[0]=0; tot=2;root=1; fa[1]=0;size[1]=2;w[1]=-inf;ch[1][1]=2; fa[2]=1;size[2]=1;w[2]=inf; scanf("%d%d",&n,&T); for (int i=1;i<=n;i++) { int x; scanf("%d",&x); insert(i,x); } while (T--) { int x,y; scanf("%s%d",s,&x); if (s[0]=='Q') printf("%d\n",w[find_k(root,x+1)]); if (s[0]=='A') printf("%d\n",query(pos[x])-1); if (s[0]=='T') del(pos[x]),insert(1,x); if (s[0]=='B') del(pos[x]),insert(n,x); if (s[0]=='I') { scanf("%d",&y); int num=query(pos[x]); del(pos[x]); insert(num+y,x); } } return 0; }