P2596 [ZJOI2006]书架

我们用fhq treap来完成这一题

对于一个新插入的节点我们取权值为其索引值,其所记录的valuevaluevalue是其当前索引所在位置。

操作一:把索引为valuevaluevalue的点放到平衡树前面,分别别得到三颗子树x,y,zx, y, zx,y,z(前段子树,索引为valuevaluevalue所代表的子树,后段子树),同时把val[y]val[y]val[y]修改成全局最小,然后按照顺序merge(y,x,z)merge(y, x, z)merge(y,x,z)。

操作二:与操作一类似得到x,y,zx, y, zx,y,z,然后把val[y]val[y]val[y]改成全局最大,按照顺序merge(x,z,y)merge(x, z, y)merge(x,z,y)。

操作三:t=0t = 0t=0不做操作,t=1t = 1t=1得到四颗子树x,y,z,wx, y, z, wx,y,z,w(前段子树,valuevaluevalue所代表的子树,valuevaluevalue的后继,后端子树),交换信息,然后按照顺序merge(x,z,y,w)merge(x, z, y, w)merge(x,z,y,w),t=−1t = -1t=−1得到四颗子树x,y,z,wx, y, z, wx,y,z,w(前段子树,valuevaluevalue的前驱,valuevaluevalue所代表的子树,后端子树),交换信息,然后按照顺序merge(x,z,y,w)merge(x, z, y, w)merge(x,z,y,w)。

操作四:按照值分裂成两棵树,然后输出第一颗树的大小即可。

操作五:直接查找第kkk大即可。

#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;mt19937 rnd(233);int minn, maxn;struct Tree {int ls[N], rs[N], val[N], sz[N], key[N], root, cnt;void push_up(int rt) {sz[rt] = sz[ls[rt]] + sz[rs[rt]] + 1;}int new_node(int value, int pos) {val[value] = pos, sz[value] = 1, key[value] = rnd();return value;}void split(int rt, int value, int &x, int &y) {if (!rt) {x = y = 0;return ;}if (val[rt] <= value) {x = rt;split(rs[rt], value, rs[rt], y);}else {y = rt;split(ls[rt], value, x, ls[rt]);}push_up(rt);}int merge(int x, int y) {if (!x || !y) {return x | y;}if (key[x] < key[y]) {rs[x] = merge(rs[x], y);push_up(x);return x;}else {ls[y] = merge(x, ls[y]);push_up(y);return y;}}int get_num(int rt, int rank) {while (rt) {if (sz[ls[rt]] + 1 == rank) {break;}if (sz[ls[rt]] >= rank) {rt = ls[rt];}else {rank -= sz[ls[rt]] + 1;rt = rs[rt];}}return rt;}int get_num(int rank) {return get_num(root, rank);}void insert(int value, int pos) {int x, y;split(root, pos, x, y);root = merge(merge(x, new_node(value, pos)), y);}void update(int value, int op) {int x, y, z;split(root, val[value], x, z);split(x, val[value] - 1, x, y);if (op) {val[value] = --minn;root = merge(merge(y, x), z);}else {val[value] = ++maxn;root = merge(merge(x, z), y);}}void reverse(int value, int op) {if (!op) {return ;}if (op == 1) {int x, y, z, w;split(root, val[value], x, z);split(x, val[value] - 1, x, y);int t = get_num(z, 1);split(z, val[t], z, w);swap(val[y], val[z]);root = merge(merge(x, z), merge(y, w));}else {int x, y, z, w;split(root, val[value] - 1, x, z);split(z, val[value], z, w);int t = get_num(x, sz[x]);split(x, val[t] - 1, x, y);swap(val[y], val[z]);root = merge(merge(x, z), merge(y, w));}}int get_rank(int value) {int x, y, ans;split(root, val[value] - 1, x, y);ans = sz[x];root = merge(x, y);return ans;}
}tree;int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int n, m;scanf("%d %d", &n, &m);minn = 1, maxn = n;for (int i = 1, x; i <= n; i++) {scanf("%d", &x);tree.insert(x, i);}char op[10];for (int i = 1, s, t; i <= m; i++) {scanf("%s %d", op, &s);if (op[0] == 'T') {tree.update(s, 1);}else if (op[0] == 'B') {tree.update(s, 0);}else if (op[0] == 'I') {scanf("%d", &t);tree.reverse(s, t);}else if (op[0] == 'A') {printf("%d\n", tree.get_rank(s));}else {printf("%d\n", tree.get_num(s));}}return 0;
}

P2596 [ZJOI2006]书架(fhq treap)相关推荐

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

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

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

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

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

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

  4. luogu P2596 [ZJOI2006]书架

    背景: 整整一天. 题目传送门: https://www.luogu.org/problemnew/show/P2596 题意: n n n本书, 5 5 5中操作. 1. 1. 1.把某本书放在最上 ...

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

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

  6. 可持久化平衡树(FHQ Treap)

    两个最基本的操作 merge合并 split分割 merge 把两棵treap合并成一棵treap,要满足T1最大值要比T2最小值小,比较将随机数值key值更大的作为合并后的根 假设T1作为根节点作为 ...

  7. FHQ Treap 详解

    0. 简单介绍 FHQ Treap,以下简写为fhq,是一种treap(树堆)的变体,功能比treap强大,代码比splay好写,易于理解,常数稍大. fhq不需要通过一般平衡树的左右旋转来保持平衡, ...

  8. FHQ Treap 总结

    [前言(一堆废话)] 目前 OI 竞赛中两大主流平衡树之一就是 FHQ Treap(另一个是 Splay). 普通 BST 的中序遍历中,val 值构成一个单调递增的序列. Treap 在 BST 的 ...

  9. Treap + FHQ Treap

    一:Treap 支持:插入.删除.查询 x x x 的排名.查询排名为 x x x 的数.查前驱.查后继.左旋右旋 模板题:P3369 [模板]普通平衡树 #include<bits/stdc+ ...

最新文章

  1. 使用VScode开发C语言程序,环境安装配置,保姆级教程
  2. 【BJDCTF 2nd—Web】做题+复现记录
  3. 《Go 语言程序设计》读书笔记 (三) 方法
  4. 开源GIS(十三)——openlayers通过geoserver中WFS添加要素
  5. 软件工程 四则运算(结对编程)
  6. NOIP2013普及组复赛第一题《计数问题》CA代码
  7. 【密码学基础】02 数论基础
  8. 在Mac上安装ie10浏览器
  9. 如何封装axios?axios 的简单封装
  10. Nvivo使用步骤记录
  11. 详解pandas编码函数pd.factorize()
  12. C++ 几种智能指针的简单实现
  13. 如何制作动态图片gif
  14. 服务器搭建网站公网ip,如何获取公网ip,自己搭建公网ip服务器的方法
  15. PHP获取客户端操作系统,游览器类型及版本号
  16. ASP.NET Web程序设计 第六章 三层架构
  17. 美式期权定价利率衍生证券
  18. HMI(人机界面)工业自动化中最前沿的解决方案
  19. word 2013 并列显示两张图片(且各自带有题注)
  20. NSSCTF刷题wp——常用编码

热门文章

  1. filegetcontents php 返回值,php – file_get_contents没有返回任何数据
  2. 16岁上大学,25岁博士毕业,她还是南大医学院最年轻的博导!
  3. 神奇却又随处可见的斐波那契曲线...
  4. 《SAS编程与数据挖掘商业案例》学习笔记之七
  5. html写出日出,描写日出优美句子
  6. kivy中文手册python_K-Meleon
  7. 查询两个日期间隔天数怎么算_大厂都是怎么用Java8代替SimpleDateFormat?
  8. mysql 5.7.6 5.7.19_MySQL数据库之Mysql 5.7.19 免安装版遇到的坑(收藏)
  9. 巨型机是一种什么的超级计算机,这个世界其实是一个超级计算机
  10. php数字转中文数字排序,php实现中文转数字