题目链接

/*
五个操作:
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. Linux 进程中 Stop, Park, Freeze【转】

    转自:https://blog.csdn.net/yiyeguzhou100/article/details/53134743 http://kernel.meizu.com/linux-proces ...

  2. 【转】htop使用详解--史上最强(没有之一)

    在管理进程时通常要借助一些工具,比较常用的就是ps和top了:不过CentOS还为我们提供了一个更加强大的工具htop,下面就来了解一下此工具的使用方法.一.安装htop htop工具在epel源中提 ...

  3. Android service与Thread

    很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下. 1). Thread:Thre ...

  4. python 运行日志logging代替方案

    以下是自己写的 记录日志的代码.(和logging不搭嘎,如果如要学loggging模块,本文末尾有他人的链接.) # prtlog.py ############################## ...

  5. swift的一些知识点(不断完善中)

    首先,隆重推荐文章http://www.infoq.com/cn/articles/swift-brain-gym-optional swift 烧脑体操!目前有4篇文章,说的都很好! 1. 应该充分 ...

  6. 【转载】如何让图片按比例响应式缩放、并自动裁剪的css技巧

    原文: http://blog.csdn.net/oulihong123/article/details/54601030 响应式网站.移动端页面在DIV CSS布局中对于图片列表或图片排版时, 如果 ...

  7. python之类中的super函数

    作用 实现代码重用 思考:super真的只是调用父类么? super函数是按照mro算法去调用的,不bb上代码: class A: def __init__(self): print('A') cla ...

  8. Laravel collection 报错 join(): Invalid arguments passed

    混淆了 array 与 collection,join 并不支持 collection. array 与 collection 不同的 join 实现 collect([1, 2, 3, 4, 5]) ...

  9. pytest十一:函数传参和 firture 传参数 request

    为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数.比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其它用例全部的调用这个登录函数就行.但是登录 ...

  10. python接口自动化测试十二:对返回的json的简单操作

    # 1.requests里面自带解析器转字典 print(r.json()) print(type(r.json())) # 取出json中的'result_sk_temp'字段 # {"r ...