[BZOJ1861][Zjoi2006]Book 书架(平衡树)
2018-03-15 23:41
351 查看
题目:
我是超链接题解:
这个书架的排序方式可以用splay维护,对于top操作来说,我们拿出编号为s的节点splay到根,因为是最上面,那么应该不能有比他小的序,所以左子树应当并到右子树的最左端,特别要注意判断没有右子树的情况,那就直接把左儿子变成右儿子。那么bottom操作也一样。对于insert操作来说,其实就是将某个位置跟ta的前缀/后缀交换,交换节点多麻烦啊,其实我们只需要交换这两个节点上的信息就好啦。
ask操作就是维护一波size
query有点像二叉树求第k大的样子
总的来说这棵平衡树维护的序是书的先后(位置),对于编号来说只需要开一个数组记录编号为s的对应哪个节点就好了
代码:
#include<cstdio> #include <iostream> using namespace std; const int N=80005; int ch [2],size ,f ,root,sz,pos ,key ; int get(int x){return ch[f[x]][1]==x;} void updata(int now){size[now]=size[ch[now][0]]+size[ch[now][1]]+1;} void rotate(int x) { int old=f[x],oldf=f[old],which=get(x); f[x]=oldf; if (oldf) ch[oldf][get(old)]=x; ch[old][which]=ch[x][which^1]; f[ch[x][which^1]]=old; ch[x][which^1]=old; f[old]=x; updata(old); updata(x); } void splay(int x) { for (;f[x];rotate(x)) if (f[f[x]]) rotate(get(x)==get(f[x])?f[x]:x); root=x; } int pre() { int now=ch[root][0]; while (ch[now][1]) now=ch[now][1]; return now; } int nxt() { int now=ch[root][1]; while (ch[now][0]) now=ch[now][0]; return now; } void insert(int x) { ++sz; pos[x]=sz; key[sz]=x; size[sz]=1; if (sz!=1) { ch[sz-1][1]=sz; f[sz]=sz-1; splay(sz); } } void top(int x) { x=pos[x]; splay(x); if (!ch[x][0]) return; if (!ch[x][1]) ch[x][1]=ch[x][0],ch[x][0]=0; else { int y=nxt(); f[ch[root][0]]=y; ch[y][0]=ch[root][0]; ch[root][0]=0; splay(y); } } void bottom(int x) { x=pos[x]; splay(x); if (!ch[x][1]) return; if (!ch[x][0]) ch[x][0]=ch[x][1],ch[x][1]=0; else { int y=pre(); f[ch[root][1]]=y; ch[y][1]=ch[root][1]; ch[root][1]=0; splay(y); } } void ins(int x) { int now=pos[x],y; int id;scanf("%d",&id); if (id==0) return; splay(now); if (id==1) y=nxt();else y=pre(); swap(pos[x],pos[key[y]]); swap(key[y],key[now]); } int find(int x) { int now=root; while (1) { if (x<=size[ch[now][0]] && ch[now][0]) now=ch[now][0]; else { x-=size[ch[now][0]]+1; if (x<=0) return key[now]; now=ch[now][1]; } } } int main() { int n,m,x;scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&x),insert(x); while (m--) { char st[10];scanf("%s",st);scanf("%d",&x); switch(st[0]) { case 'T':top(x);break; case 'B':bottom(x);break; case 'I':ins(x);break; case 'A':splay(pos[x]);printf("%d\n",size[ch[root][0]]);break; case 'Q':printf("%d\n",find(x));break; } } }
相关文章推荐
- bzoj1861: [Zjoi2006]Book 书架 平衡树 Splay
- 【平衡树】【pb_ds】 bzoj1861 [Zjoi2006]Book 书架
- BZOJ 1861: [Zjoi2006]Book 书架 | SPlay 板题
- BZOJ 1861 ZJOI 2006 Book 书架 Splay
- 【BZOJ 1861】[Zjoi2006]Book 书架 splay
- BZOJ1861 [Zjoi2006]Book 书架
- bzoj 1861 [Zjoi2006]Book 书架
- [bzoj1861][Zjoi2006]Book书架 splay
- BZOJ1861 [Zjoi2006]Book 书架
- 【权值分块】bzoj1861 [Zjoi2006]Book 书架
- BZOJ1861: [Zjoi2006]Book 书架 Splay
- bzoj1861 [Zjoi2006]Book 书架
- BZOJ1861: [Zjoi2006]Book 书架
- bzoj 1861: [Zjoi2006]Book 书架
- [BZOJ1861] [Zjoi2006]Book 书架
- 【BZOJ1861】【Zjoi2006】Book 书架 Splay
- BZOJ 1861: [Zjoi2006]Book 书架
- splay伸展树基础操作(bzoj 1861: [Zjoi2006]Book 书架)
- 【bzoj1861】[Zjoi2006]Book 书架 splay
- BZOJ 1861: [Zjoi2006]Book 书架 (splay)