P2596 [ZJOI2006]书架(splay)
[题目链接] 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)的更多相关文章
- P2596 [ZJOI2006]书架 && Splay 区间操作(三)
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- 洛谷 P2596 [ZJOI2006]书架 (splay)
题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...
- 洛谷 P2596 [ZJOI2006]书架 解题报告
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架
题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...
- [洛谷P2596] [ZJOI2006]书架
洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...
- luogu P2596 [ZJOI2006]书架
传送门 感觉要死在\(Splay\)里了 orz 这题用\(Splay\)维护这个序列,其中的第\(k\)大点代表这个序列的第\(k\)个数 第一个操作,先把那个数所在的点旋到根,然后把整个根的左子树 ...
- 洛谷.2596.[ZJOI2006]书架(Splay)
题目链接 /* 五个操作: 1.将某元素置顶.删掉这个数,插入最左 2.将某元素置底.同样 3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点! 4.5.裸平衡树 ps:1.用pos[ ...
- P2596 [ZJOI2006]书架
思路 一开始写fhq-treap 感觉越写越感觉splay好些,就去splay 然后维护序列 注意前驱后继的不存在的情况 但不用插入虚拟节点(那插入岂不太麻烦) 跑的真慢的一批,splay太多了 错误 ...
- BZOJ1861:[ZJOI2006]书架(Splay)
Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...
随机推荐
- linux命令-sudo普通用户拥有root权限
普通用户权限不够 [root@wangshaojun ~]# su - dennywang[dennywang@wangshaojun ~]$ ls /root/ls: 无法打开目录/root/: 权 ...
- LaTeX数学公式基础
LaTeX数学公式 参考:https://www.cnblogs.com/Sinte-Beuve/p/6160905.html 原博客显示有点问题,重新搬运整理LaTeX数学公式部分的基本用法 基础 ...
- Android 数据库 OrmLite Failed to open database
04-01 16:49:32.720: E/SQLiteLog(1894): (14) cannot open file at line 30204 of [00bb9c9ce4]04-01 16:4 ...
- 3-2 zk客户端连接关闭服务端,查看znode
使用ZooKeeper官方提供的Client来连接.路径类似的结构. 连接到我们的门户HOST. quota属于zookeeper.quota是子节点,zookeeper是父节点.quota其实是一个 ...
- static、静态变量、静态方法
1 静态:static 1.1 用法 是一个修饰符:用于修饰成员(成员变量和成员函数) 1.2 好处 当成员变量被静态static修饰后,就多了一种调用方式,除了可以被对象调用外,还可以直接被类名调用 ...
- STM32 C++编程 005 I2c(Soft)类
使用 C++ 语言给 STM32 编写一个 I2c(Soft)类 我使用的STM32芯片:STM32F103ZET6 我们使用的STM32库版本:V3.5.0 注意: 想学习本套 STM32 C++编 ...
- oracle环境变量配置
1.右键我的电脑--->属性--->高级系统设置 2.环境变量---->新建 总共配置三个变量(1) 变量名 ORACLE_HOME 变量值 G:\app\TH\product\11 ...
- 《Effective Java》第4章 类和接口
第13条:使类和成员的可访问性最小化 第一规则很简单:尽可能地使每个类或者成员不被外界访问.换句话说.应该使用与你正在编写的软件的对应功能相一致的.尽可能最小的访问级别. 对于顶层的(非嵌套的)类和接 ...
- execve(".. ",[".. ",".. "],[/* ..*/])第二个 参数 数组硬传
strace.第一次跟踪点东西的启动. 第一次看见..execve(".. ",[".. ",".. "],[/* ..*/]) 第二个 参 ...
- symbol访问法及symbor注册表
symbol主要作用是防止对象属性名冲突 在ES6之前,对象的属性名只能是字符串,这样很容易造成字符串的冲突. 例:假设person对象是从外部库引入的一个对象 let person = { name ...