题目链接

/*
五个操作:
1.将某元素置顶。删掉这个数,插入最左
2.将某元素置底。同样
3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点!
4.5.裸平衡树
ps:1.用pos[i]表示第i本书在树上对应的节点,会方便很多(虽然复杂的我也不会)。注意比较的是pos,再开个数组
2.交换信息交换记录有用信息的pos和t即可。注意pos是t值的位置,换的是pos[tx],pos[ty]
3.pos[v]即v现在的位置,平衡树中正是以下标位置为排序标准的。将v旋到根即Splay(pos[v],root)
4.找前驱可以直接return Rank(sz[x]-1),后继同理
5.删除节点可以利用该节点的排名,将前驱旋到根上,后继旋到son[root][1],就可以直接删掉这个点
6.加入两个哨兵节点 操作1.2就会非常容易 不明白Move中Bottom为什么是找第n和n+1...
*/
#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
const int N=8e4+5; int n,m,root,pos[N],t[N],sz[N],son[N][2],fa[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
} inline void Update(int rt)
{
sz[rt]=sz[son[rt][0]]+sz[son[rt][1]]+1;
}
void Build(int l,int r,int f)
{
if(l>r) return;
int m=l+r>>1;
fa[m]=f, son[f][m>f]=m, sz[m]=1;
if(l==r) return;
Build(l,m-1,m), Build(m+1,r,m);
Update(m);
}
void Rotate(int x,int &k)
{
int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
if(a==k) k=x;
else son[b][son[b][1]==a]=x;
fa[x]=b, fa[a]=x, fa[son[x][r]]=a;
son[a][l]=son[x][r], son[x][r]=a;
Update(a), Update(x);
}
void Splay(int x,int &k)
{
while(x!=k)
{
int a=fa[x],b=fa[a];
if(a!=k) (son[a][1]==x^son[b][1]==a)?Rotate(x,k):Rotate(a,k);
Rotate(x,k);
}
}
int Rank(int v,int k)
{
while(1)
{
if(sz[son[k][0]]+1==v) return k;
if(sz[son[k][0]]>=v) k=son[k][0];
else v-=sz[son[k][0]]+1,k=son[k][1];
}
}
//void Delete(int v)
//{
// int k=root;
// if(son[k][0]&&son[k][1])
// {
// int p=son[k][0];root=k=son[k][1];
// while(son[k][0]) k=son[k][0];
// fa[p]=k, son[k][0]=p, sz[k]+=sz[p];
// Splay(k,root);
// }
// else root=son[k][0]|son[k][1];
// fa[root]=0;
//}
void Delete(int k)
{
int a=Rank(k-1,root),b=Rank(k+1,root);
Splay(a,root), Splay(b,son[a][1]);
fa[son[b][0]]=sz[son[b][0]]=0, son[b][0]=0;
Update(b), Update(a);
}
void Move(int x,int v)
{
Splay(x,root);
int rank=sz[son[x][0]]+1;
Delete(rank);
int a,b;
if(v==N) a=Rank(1,root),b=Rank(2,root);
else if(v==-N) a=Rank(n,root),b=Rank(n+1,root);//n+1 n+2?
// else a=Rank(rank+v-1,root),b=Rank(rank+v,root);
Splay(a,root),Splay(b,son[a][1]);
sz[x]=1, fa[x]=b, son[b][0]=x;
Update(b), Update(a);
}
void Swap(int x,int y,int w)
{
while(son[y][w]) y=son[y][w];
std::swap(t[x],t[y]);
std::swap(pos[t[x]],pos[t[y]]);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("2596.in","r",stdin);
#endif n=read(),m=read();
for(int i=2;i<=n+1;++i) t[i]=read(),pos[t[i]]=i;
Build(1,n+2,0);//Print(1+n>>1),putchar('\n');
root=3+n>>1;
char s[10];int v,k,p,x;
while(m--)
{
scanf("%s",s),v=read();
if(s[0]=='T')
{
Move(pos[v],N);
// WA: v=pos[v], Splay(v,root), p=root, Delete(v);
// x=root;
// while(son[x][0]) x=son[x][0];
// fa[p]=x, son[p][0]=son[p][1]=0, sz[p]=1;
// son[x][0]=p, ++sz[x];
// Splay(x,root);
}
else if(s[0]=='B')
{
Move(pos[v],-N);
// WA: v=pos[v], Splay(v,root), p=root, Delete(v);
// x=root;
// while(son[x][1]) x=son[x][1];
// fa[p]=x, son[p][0]=son[p][1]=0, sz[p]=1;
// son[x][1]=p, ++sz[x];
// Splay(x,root);
}
else if(s[0]=='I')
{
// k=read(), Move(pos[v],k);
k=read(), Splay(pos[v],root);
if(k==-1) Swap(root,son[root][0],1);
else if(k==1) Swap(root,son[root][1],0);
}
else if(s[0]=='A') Splay(pos[v],root),printf("%d\n",sz[son[root][0]]-1);
else printf("%d\n",t[Rank(v+1,root)]);
} return 0;
}

洛谷.2596.[ZJOI2006]书架(Splay)的更多相关文章

  1. 洛谷 P2596 [ZJOI2006]书架 (splay)

    题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...

  2. [洛谷P2596] [ZJOI2006]书架

    洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...

  3. 洛谷 P2596 [ZJOI2006]书架 解题报告

    P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...

  4. [Luogu 2596] ZJOI2006 书架

    [Luogu 2596] ZJOI2006 书架 第一次指针写 FHQ_Treap(省选噩梦数据结构)AC 啦! 省选试机写它,紧张过度失败了. 省选 Day 1 考场写它,写挂了. 省选 Day 1 ...

  5. BZOJ3224/洛谷P3391 - 普通平衡树(Splay)

    BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...

  6. P2596 [ZJOI2006]书架 && Splay 区间操作(三)

    P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...

  7. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  8. [洛谷P2584][ZJOI2006]GameZ游戏排名系统

    题目大意:同[洛谷P4291][HAOI2008]排名系统(双倍经验) 题解:略 卡点:无 C++ Code: #include <cstdio> #include <map> ...

  9. BZOJ1861:[ZJOI2006]书架(Splay)

    Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...

随机推荐

  1. SharePoint 2013 Workflow Manager 1.0 远程服务器返回错误: (400) 错误的请求。 不支持查询字符串中的 api-version

    环境: Windows Server 2012 R2 Standard SharePoint Server 2013 with sp1 通过Web 平台安装程序 5.0,已安装 Workflow Ma ...

  2. dell R720服务器设置开机启动顺序

    开机按F2进入系统启动设置,也可以按F11进入快速启动配置

  3. Future、 CompletableFuture、ThreadPoolTaskExecutor简单实践

    一 Future(jdk5引入) 简介: Future接口是Java多线程Future模式的实现,可以来进行异步计算. 可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算 ...

  4. Android动画分类

    动画分类 View动画(补间动画).帧动画.属性动画 View动画(补间动画)包括:平移.旋转.缩放.透明度,View动画是一种渐近式动画 帧动画:图片切换动画 属性动画:通过动态改变对象的属性达到动 ...

  5. PLSQL developer 连接不上64位Oracle 解决办法

    在64位Windows7上安装Oracle后,用PLSQL developer去连接数据库出现报错: Could not load "……\bin\oci.dll" OCIDLL ...

  6. redis介绍以及安装

    一.redis介绍 redis是一个key-value存储系统.和Memcached类似,它支持存储的values类型相对更多,包括字符串.列表.哈希散列表.集合,有序集合. 这些数据类型都支持pus ...

  7. appium自动化测试之元素定位

    方法一 使用SDK中附带的uiautomatorviewer来定位 在SDK安装目录下的tools下有个uiautomatorviewer.bat批处理文件点击运行 运行后(注意appium desk ...

  8. 方法名太多,使用方法的重载(overload)来解决

    package chapter04; /* 问题:方法名太多了,不容易记忆,有时会出错 使用方法的重载(overload)来解决 */public class C09_Method { public ...

  9. Redis设置Key/value的规则定义和注意事项(附工具类)

    对于redis的存储key/value键值对,经过多次踩坑之后,我们总结了一套规则:这篇文章主要讲解定义key/value键值对时的定义规则和注意事项. 前面一篇文章讲了如何定义Redis的客户端和D ...

  10. Git强制更新本地库和冲突解决

    1.You have not concluded your merge. (MERGE_HEAD exists) 本地有修改和提交,如何强制用远程的库更新.出现这种情况一般是git本地有commit, ...