背景:

整整一天。

题目传送门:

https://www.luogu.org/problemnew/show/P2596

题意:

n n n本书, 5 5 5中操作。
1. 1. 1.把某本书放在最上面;
2. 2. 2.把某本书放在最下面;
3. 3. 3.把这本书放在原位置的附近( ± 1 \pm1 ±1内);
4. 4. 4.询问某本书上面有多少本书;
5. 5. 5.询问自上而下某本书的编号。

思路:

鉴于这里有两个值(编号和高度)要维护,不妨考虑使 s p l a y splay splay中第 i i i个点维护编号为 i i i的书的高度。

考虑操作 1 , 2 1,2 1,2,由于这道题并不需要知道确切的高度(只需要知道相对高度的排名),因此有简单的维护方法。最上面和最下面对应的就是高度最小和最大,每一次将这本书删除,再在同一编号的节点塞入最小或最大值(高度)即可。

考虑操作 3 3 3,其实就是交换前驱或后继的高度,但是由于 s p l a y splay splay并不支持自动维护成平衡树,因此要先删除后加入(注意要先删完,在加入,不然就会有两个高度相同的点在 s p l a y splay splay中)。

操作 4 , 5 4,5 4,5其实就是模板,询问某个点的排名和排名为某个值的编号。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;struct node1{int d,fa,c,son[2];} tr[200010];struct node2{int x,id;} a[200010];int n,m,root=0,len=0,mi=1,ma;
bool cmp(node2 x,node2 y)
{return x.x<y.x;
}
void ups(int x)
{tr[x].c=tr[tr[x].son[0]].c+tr[tr[x].son[1]].c+1;
}
void add(int d,int fa)
{tr[++len]=(node1){d,fa,1,{0,0}};
}
void rot(int x,int w)//左旋:0,右旋:1
{int y=tr[x].fa,yy=tr[y].fa;tr[y].son[1^w]=tr[x].son[w];if(tr[x].son[w]) tr[tr[x].son[w]].fa=y;tr[yy].son[tr[yy].son[0]==y?0:1]=x;tr[x].fa=yy,tr[x].son[w]=y,tr[y].fa=x;ups(y),ups(x);
}
void splay(int x,int rt)
{while(tr[x].fa!=rt){int y=tr[x].fa,yy=tr[y].fa;if(yy==rt){rot(x,tr[y].son[0]==x?1:0);continue;}if(tr[yy].son[0]==y){if(tr[y].son[0]==x) rot(y,1),rot(x,1); else rot(x,0),rot(x,1);continue;}if(tr[y].son[1]==x) rot(y,0),rot(x,0); else rot(x,1),rot(x,0); }if(!rt) root=x;
}
int findip(int x,int d)
{if(d==tr[x].d) return x;if(d<tr[x].d)return tr[x].son[0]?findip(tr[x].son[0],d):x;elsereturn tr[x].son[1]?findip(tr[x].son[1],d):x;
}
void ins(int d)
{if(!root){add(d,0);root=1;return;}int u=findip(root,d);add(d,u);tr[u].son[d<tr[u].d?0:1]=len;ups(u);splay(len,0);
}
void ins2(int x,int d)
{int u=findip(root,d);tr[x]=(node1){d,u,1,{0,0}};tr[u].son[d<tr[u].d?0:1]=x;ups(u);splay(x,0);
}
void del(int u)
{splay(u,0);if(!tr[u].son[0]&&tr[u].son[1]){root=tr[u].son[1];tr[root].fa=0;tr[u]=(node1){0,0,0,{0,0}};return;}if(tr[u].son[0]&&!tr[u].son[1]){root=tr[u].son[0];tr[root].fa=0;tr[u]=(node1){0,0,0,{0,0}};return;}int o=tr[u].son[0];while(tr[o].son[1]) o=tr[o].son[1];splay(o,u);tr[o].son[1]=tr[u].son[1];tr[tr[o].son[1]].fa=o;root=o;tr[o].fa=0;ups(o);tr[u]=(node1){0,0,0,{0,0}};
}
int findnum(int x,int d)
{int lc=tr[x].son[0],rc=tr[x].son[1];if(d<=tr[lc].c) return findnum(lc,d);else if(d>tr[lc].c+1) return findnum(rc,d-tr[lc].c-1);else return x;
}
int findrank(int x)
{splay(x,0);return tr[tr[x].son[0]].c;
}
void work_T(int x)
{del(x);ins2(x,--mi);
}
void work_B(int x)
{del(x);ins2(x,++ma);
}
int findqianqu(int u)
{splay(u,0);u=tr[u].son[0];while(tr[u].son[1]) u=tr[u].son[1];return u;
}
int findhouji(int u)
{splay(u,0);u=tr[u].son[1];while(tr[u].son[0]) u=tr[u].son[0];return u;
}
void work(int x,int y)
{if(!y) return;int u;if(y==-1) u=findqianqu(x); else u=findhouji(x);int d1=tr[u].d,d2=tr[x].d;del(x),del(u);ins2(x,d1),ins2(u,d2);
}
int main()
{int x,y;char s[10];scanf("%d %d",&n,&m);ma=n;for(int i=1;i<=n;i++){scanf("%d",&a[i].x);a[i].id=i;}sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++)ins(a[i].id);for(int i=1;i<=m;i++){scanf("%s",s+1);if(s[1]=='T'){scanf("%d",&x);work_T(x);}else if(s[1]=='B'){scanf("%d",&x);work_B(x);}else if(s[1]=='I'){scanf("%d %d",&x,&y);work(x,y);}else if(s[1]=='A'){scanf("%d",&x);printf("%d\n",findrank(x));}else if(s[1]=='Q'){scanf("%d",&x);printf("%d\n",findnum(root,x));}}
}

luogu P2596 [ZJOI2006]书架相关推荐

  1. luogu P2596 [ZJOI2006]书架(平衡树、无旋treap(按排名分裂)一些更复杂的操作)

    P2596 [ZJOI2006]书架 无旋treap可以维护一棵树的中序遍历结果.但是不支持通过编号来找节点.于是在无旋treap的基础上,我维护了每个节点的父亲,这样就可以求出一个节点是中序遍历中的 ...

  2. P2596 [ZJOI2006]书架(fhq treap)

    P2596 [ZJOI2006]书架 我们用fhq treap来完成这一题 对于一个新插入的节点我们取权值为其索引值,其所记录的valuevaluevalue是其当前索引所在位置. 操作一:把索引为v ...

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

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

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

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

  5. P2596 [ZJOI2006]书架 无旋treap 按照排名分裂

    传送门 文章目录 题意: 思路: 题意: 实现如下操作: 思路: fhq-treap板子辣,不要被他的编号误导了,我们还是需要按照排名来分裂,从上到下标号1−n1-n1−n即可,注意在按照排名分裂的时 ...

  6. luogu P3850 [TJOI2007]书架(平衡树、无旋treap(按排名分裂))

    luogu P3850 [TJOI2007]书架 这里要的是字符串,所以我们最好用一个map映射一下,不要在结构体中用string代替val. fhq-treap中所有的排名实际上都指的是前面有多少个 ...

  7. luogu P2584 [ZJOI2006]GameZ游戏排名系统 Splay

    luogu P2584 [ZJOI2006]GameZ游戏排名系统 Splay 实在不想调了QAQ... Code: #include <cstdio> #include <algo ...

  8. BZOJ 1859 Luogu P2589 [ZJOI2006]碗的叠放 (计算几何)

    woc, 13年前的ZJOI就这么毒瘤的嘛... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=1859 (luogu)ht ...

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

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

最新文章

  1. iOS应用开发入门(3)——点击button控制textview
  2. html实战例子: 简易的qq登录界面
  3. Jave之Scanner和不合法输入处理
  4. 编写高性能 .NET 代码 第二章:垃圾回收 基本操作
  5. 【Python】Matplotlib画布图案保存为PDF文件
  6. 如何对CAD进行区域覆盖
  7. 定义一个Point类,派生出Circle类,计算各派生类对象的面积Area()
  8. centOS6.6虚拟机启动后登陆界面无法显示
  9. Ubuntu18.04安装中文字体SimHei
  10. 2021年4月自考04741计算机网络原理试卷
  11. 报Failed to resolve: org.jetbrains.kotlin:kotlin-stdlib-jre7的错误
  12. DTU服务器接收软件
  13. 使用 Bitmap Style Designer 为FMX修改已有样式
  14. 集线器故障诊断与排除
  15. SOX命令:音频位深度、采样率以及码率
  16. python画一箭穿心_turtle的简单绘图
  17. JS学习笔记:Javascript给对象增加属性(函数作为属性)
  18. Serv-u + 花生壳实现FTP内网穿透
  19. 直播预告 | openGauss自治运维能力的技术演进分享
  20. 三言|一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石

热门文章

  1. 联想yoga710评测_YOGA新本性能担当 联想YOGA 710 14评测
  2. 婴儿的出生为你解惑构造函数和构造代码块
  3. 舍友打了几把英雄联盟,C语言数组归纳(一)就被完成了
  4. 物联网和区块链有什么联系
  5. 联想笔记本触摸板失灵(解决方法)
  6. 选购二手房的流程和注意事项
  7. 电视hdmi接口在哪_笔记本如何连接电视机?电视秒变电脑屏
  8. vs2010 MSDN文档安装方法(转自:http://www.ljf.cn/archives/91.aspx)
  9. 全球公认的国际标准 EcoVadis审计,如何获得勋章
  10. 软考是什么?软考的考试安排是什么时候?