洛谷.2596.[ZJOI2006]书架(Splay)
/*
五个操作:
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)的更多相关文章
- 洛谷 P2596 [ZJOI2006]书架 (splay)
题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...
- [洛谷P2596] [ZJOI2006]书架
洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...
- 洛谷 P2596 [ZJOI2006]书架 解题报告
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- [Luogu 2596] ZJOI2006 书架
[Luogu 2596] ZJOI2006 书架 第一次指针写 FHQ_Treap(省选噩梦数据结构)AC 啦! 省选试机写它,紧张过度失败了. 省选 Day 1 考场写它,写挂了. 省选 Day 1 ...
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...
- P2596 [ZJOI2006]书架 && Splay 区间操作(三)
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- [洛谷P2584][ZJOI2006]GameZ游戏排名系统
题目大意:同[洛谷P4291][HAOI2008]排名系统(双倍经验) 题解:略 卡点:无 C++ Code: #include <cstdio> #include <map> ...
- BZOJ1861:[ZJOI2006]书架(Splay)
Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...
随机推荐
- ioremap 与 mmap【转】
转自:http://blog.csdn.net/junllee/article/details/7415732 内存映射 对于提供了MMU(存储管理器,辅助操作系统进行内存管理,提供虚实地址转换等硬件 ...
- kafka系列九、kafka事务原理、事务API和使用场景
一.事务场景 最简单的需求是producer发的多条消息组成一个事务这些消息需要对consumer同时可见或者同时不可见 . producer可能会给多个topic,多个partition发消息,这些 ...
- 自动化监控白皮书——WAS监控
WebSphere(WAS)是一些大型企业常用的中间件,由于was自身提供的工具有时不能满足多样化的监控需求,而我们又会经常遇到对was进行监控的应用场景,所以我们有必要自己动手做一些was的监控脚本 ...
- AS 中 Plugin for Gradle 和 Gradle 之间的版本对应关系
Plugin for Gradle 和 Gradle 之间的版本对应关系 来源:https://developer.android.com/studio/releases/gradle-plugin. ...
- mac安装navicat mysql破解版
下载破解中文版http://m6.pc6.com/xuh6/navicat12027pre.zip 完成下载后无法正常进行安装,此时应该打开命令行执行 sudo spctl --master-disa ...
- collectd+influxDB+Grafana搭建性能监控平台
网上查看了很多关于环境搭建的文章,都比较久远了很多安装包源都不可用了,今天收集了很多资料组合尝试使用新版本来搭建,故在此记录. 采集数据(collectd)-> 存储数据(influxdb) - ...
- 《剑指offer》-表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123","3.1416&q ...
- HDU 1075 字符串映射(map)
Sample InputSTARTfrom fiwohello difhmars riwosfearth fnnvklike fiiwjENDSTARTdifh, i'm fiwo riwosf.i ...
- POJ 3614 Sunscreen (优先队列)
题意:奶牛美容:有C头奶牛日光浴,每头奶牛分别需要minSPF_i和maxSPF_i单位强度之间的阳光.现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i.求最多满足多少头奶牛 ...
- 使用Maven进行多模块拆分
模块拆分是Maven经常使用的功能,简单梳理一下如何使用Maven进行多模块拆分, 只做归纳总结,网上资料很多,不再一步一步实际创建和部署. 建立Maven多模块项目 一个简单的Java Web项目, ...