[题目链接] https://www.luogu.org/problemnew/show/P2596

平衡树,需支持五个操作:

1、 将某元素置顶:将元素旋到根,然后将左子树合并到该元素的后继

2、 将某元素置底:将元素旋到根,然后将右子树合并到该元素的前驱

3、 将某元素提前/滞后1位:直接与该元素的前驱/后继交换位置及信息

4、 询问指定元素排名:将元素旋到根,输出size-1

5、 询问指定排名元素:在树上find

必须维护每个点的位置,才能对它操作,不然找不到它

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
} const int MAXN=80005; namespace splay{
int ch[MAXN][2],par[MAXN],num[MAXN],pos[MAXN],size[MAXN];
int Ncnt,rt; inline bool chk(int x){
return ch[par[x]][1]==x;
} inline void pushup(int x){
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
pos[num[ch[x][0]]]=ch[x][0],pos[num[ch[x][1]]]=ch[x][1];
} inline void rotate(int x){
int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
ch[y][k]=w;par[w]=y;
ch[z][chk(y)]=x;par[x]=z;
ch[x][k^1]=y;par[y]=x;
pushup(y);pushup(x);
} inline void splay(int x,int goal=0){
while(par[x]!=goal){
int y=par[x],z=par[y];
if(z!=goal){
if(chk(x)==chk(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(!goal) rt=x;
} inline void insert1(int val){
ch[rt][1]=++Ncnt,num[Ncnt]=val,par[Ncnt]=rt,size[Ncnt]=1;//按顺序插入,直接放在最右边(中序遍历保证正确性)
splay(Ncnt);
} inline void top(int x){//旋到根节点,把左儿子接到它的后继
splay(pos[x]);
if(!ch[rt][0]) return;
if(!ch[rt][1]) ch[rt][1]=ch[rt][0],ch[rt][0]=0;
else{
int suc=ch[rt][1];
while(ch[suc][0]) suc=ch[suc][0];
ch[suc][0]=ch[rt][0];
par[ch[rt][0]]=suc;
ch[rt][0]=0;
splay(ch[suc][0]);
}
} inline void bottom(int x){//旋到根节点,把右儿子接到它的前驱
splay(pos[x]);
if(!ch[rt][1]) return;
if(!ch[rt][0]) ch[rt][0]=ch[rt][1],ch[rt][1]=0;
else{
int pre=ch[rt][0];
while(ch[pre][1]) pre=ch[pre][1];
ch[pre][1]=ch[rt][1];
par[ch[rt][1]]=pre;
ch[rt][1]=0;
splay(ch[pre][1]);
}
} inline void insert2(int x,int t){
if(t==0) return;
splay(pos[x]);
if(t==1){
int suc=ch[rt][1];
while(ch[suc][0]) suc=ch[suc][0];
int ps=pos[x];
swap(pos[x],pos[num[suc]]);//交换信息
swap(num[ps],num[suc]);
}
if(t==-1){
int pre=ch[rt][0];
while(ch[pre][1]) pre=ch[pre][1];
int ps=pos[x];
swap(pos[x],pos[num[pre]]);
swap(num[ps],num[pre]);
}
} inline int kth(int k){
int cur=rt;
while(1){
if(k<=size[ch[cur][0]]) cur=ch[cur][0];
else if(k==size[ch[cur][0]]+1) return num[cur];
else k-=size[ch[cur][0]]+1,cur=ch[cur][1];
}
} inline int query(int x){
splay(pos[x]);
return size[ch[rt][0]];
}
}using namespace splay; int n,m; int main(){
n=read(),m=read();
for(int i=1;i<=n;i++) insert1(read());
for(int i=1;i<=m;i++){
char s[10];
scanf("%s",s);
switch (s[0]){
case 'T': top(read()); break;
case 'B': bottom(read()); break;
case 'I':{
int x=read(),y=read();
insert2(x,y);
break;
}
case 'Q': printf("%d\n",kth(read())); break;
case 'A': printf("%d\n",query(read())); break;
}
}
}

P2596 [ZJOI2006]书架(splay)的更多相关文章

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

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

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

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

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

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

  4. fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架

    题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...

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

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

  6. luogu P2596 [ZJOI2006]书架

    传送门 感觉要死在\(Splay\)里了 orz 这题用\(Splay\)维护这个序列,其中的第\(k\)大点代表这个序列的第\(k\)个数 第一个操作,先把那个数所在的点旋到根,然后把整个根的左子树 ...

  7. 洛谷.2596.[ZJOI2006]书架(Splay)

    题目链接 /* 五个操作: 1.将某元素置顶.删掉这个数,插入最左 2.将某元素置底.同样 3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点! 4.5.裸平衡树 ps:1.用pos[ ...

  8. P2596 [ZJOI2006]书架

    思路 一开始写fhq-treap 感觉越写越感觉splay好些,就去splay 然后维护序列 注意前驱后继的不存在的情况 但不用插入虚拟节点(那插入岂不太麻烦) 跑的真慢的一批,splay太多了 错误 ...

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

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

随机推荐

  1. ORA-00600:内部错误代码,参数:[kpnxdcbk-2],[],[],[],[],[],[],[],[],[],[],[]

    由于最近工作中常出现ORA-00600:内部错误代码,参数:[kpnxdcbk-2],[],[],[],[],[],[],[],[],[],[],[]这种异常!所以在这里讲一下我的处理方法. 笔者所遇 ...

  2. DAY10-MYSQL数据类型

    一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob.com/mysql/mysql-data ...

  3. DAY5-常用模块

    一 time与datetime模块 二.random模块 三.os模块 四.sys模块 五 shutil模块 六 json&pickle模块 七 shelve模块 八 xml模块 九 conf ...

  4. C++之deque

    deque(包含头文件#include<deque>)由若干段连续空间串接而成,一旦有必要在deque的头部或尾端增加新的空间,便配置一段定量连续的空间,串接在deque的头部或尾端.de ...

  5. Tornado模板配置

    #!/usr/bin/env python # -*- coding:utf-8 -*- #tornado模板配置 import tornado.ioloop import tornado.web c ...

  6. IDEA创建MAVEN 无骨架WEB 项目

    Idea创建maven带有骨架的web项目的时候,会缺少必要文件夹,而且会多出来一些我们不需要的东西 详见:IDEA创建Maven Web项目 所以我们也可以创建无骨架项目: 创建maven项目 不选 ...

  7. AbstractFactoryPattern(23种设计模式之一)

    设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计模式六大 ...

  8. p4570 [BJWC2011]元素

    传送门 分析 对法力值从大到小排序然后对编号跑线性基即可 代码 #include<iostream> #include<cstdio> #include<cstring& ...

  9. jquery 使用记录

    1.jquery 筛选一个属性符合多个条件  var myTag=$("input[id=myid][name=myname][type=button]").length; 2.j ...

  10. [学习笔记]man手册的使用