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在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...
随机推荐
- UML在实践中的现状和一些建议
本文是我在csdn上看到的文章,由于认识中的共鸣,摘抄至此. 原文地址:http://blog.csdn.net/vrman/article/details/280157 UML在国内不少地方获得了应 ...
- spring 的aop操作
- VS2010 rdlc报表无法显示“数据源”选项
- Android按钮单击事件的四种常用写法
这篇文章主要介绍了Android按钮单击事件的四种常用写法总结,比较了常见的四种写法的优劣,有不错的参考借鉴价值,需要的朋友可以参考下 很多学习Android程序设计的人都会发现每个人对代码的写法都有 ...
- [poj1703]Find them, Catch them(种类并查集)
题意:食物链的弱化版本 解题关键:种类并查集,注意向量的合成. $rank$为1代表与父亲对立,$rank$为0代表与父亲同类. #include<iostream> #include&l ...
- 32-回文字符串(dp)
http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=37 回文字符串 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描 ...
- 除了ROS ,机器人自主定位导航还能怎么做?
博客转载自:https://www.leiphone.com/news/201609/10QD7yp7JFV9H9Ni.html 雷锋网(公众号:雷锋网)按:本文作者科技剪刀手,思岚科技技术顾问. 随 ...
- Node.js 介绍及学习
Node.js => 简单来理解,就是指运行在服务器端的JavaScript. Node.js 是一个基于Chrome JavaScript运行时建立的一个平台 Node.js是一个事件驱动I ...
- (数组)对数组中的数字加1(plus one)
题目:https://www.nowcoder.com/practice/4d135ddb2e8649ddb59ee7ac079aa882?tpId=46&tqId=29111&tPa ...
- [译]在Javascript中将string转化成numbers
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...