[题目链接] 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. 从文件中读取yuv和h264数据

    1.从文件中读取h264数据 参考ffmpeg avc.c写的从文件中一帧帧读取h.264数据的demo #include <stdio.h> #include <stdlib.h& ...

  2. centos 安装 python flask 和python3安装flask

    pip install Flask python3安装 pip3 install flask

  3. ROS Learning-026 (提高篇-004 A Mobile Base-02) 控制移动平台 --- “分封制”

    ROS 提高篇 之 A Mobile Base-02 - 控制移动平台 - "分封制" 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ub ...

  4. c语言输入数据

    比如要求输入一行数据(注意:没有给出输入多少个),并且以空格隔开那么就可以如下进行判断 '; ],temp,i=; while(c!='\n') { scanf("%d%c",&a ...

  5. 正割、余割、正弦、余弦、正切、余切之间的关系的公式 sec、csc与sin、cos、tan、cot之间的各种公式

    1.倒数关系 tanα ·cotα=1 sinα ·cscα=1 cosα ·secα=1 2.商数关系 tanα=sinα/cosα cotα=cosα/sinα 3.平方关系 sinα²+cosα ...

  6. kaggle House_Price_XGBoost

    kaggle House_Price_final 代码 import numpy as np import pandas as pd from sklearn.ensemble import Rand ...

  7. kaggle gradient_descent

    kaggle gradient_descent 1.描述 自写梯度下降 2.代码 import numpy as np import matplotlib.pyplot as plt # train_ ...

  8. 数据结构_Summary

    问题描述 可怜的 Bibi 丢了好几台手机以后,看谁都像是小偷,他已经在小本本上记下了他认为的各个地点的小偷数量.现在我们将 Bibi 的家附近的地形抽象成一棵有根树. 每个地点都是树上的一个节点,节 ...

  9. Python--socket和threading编程

    网络编程基础(一) TCP/IP协议 OSI/RM协议 特点:独立于计算机硬件和操作系统,统一分配网络地址,提供可靠服务,隔离了物理网络的硬件差异 协议分层(百度):网络接口层:IEE802.3(以太 ...

  10. 处理器适配器(handlerAdapter)执行源码分析(涉及到适配器模式)(九)

    适配器:实现很多接口统一管理. DispatcherServlet 组建的默认配置 HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter,A ...