「luogu3380」【模板】二逼平衡树(树套树)

传送门

我写的树套树——线段树套平衡树。

线段树上的每一个节点都是一棵 \(\text{FHQ Treap}\) ,然后我们就可以根据平衡树的基本操作以及线段树上区间信息可合并的性质来实现了,具体细节看代码都懂。

参考代码:

#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
} const int _ = 50010, __ = 2000010, INF = 2147483647; int n, m, A[_];
int tot, ch[2][__], siz[__], pri[__], val[__]; struct node {
int rt, a, b, c; inline int Newnode(int v) { return siz[++tot] = 1, val[tot] = v, pri[tot] = rand(), tot; } inline void pushup(int p) { siz[p] = siz[ch[0][p]] + siz[ch[1][p]] + 1; } inline void split(int p, int v, int& x, int& y) {
if (!p) { x = y = 0; return ; }
if (val[p] <= v) return x = p, split(ch[1][p], v, ch[1][x], y), pushup(p);
else return y = p, split(ch[0][p], v, x, ch[0][y]), pushup(p);
} inline int merge(int x, int y) {
if (!x || !y) return x + y;
if (pri[x] > pri[y]) return ch[1][x] = merge(ch[1][x], y), pushup(x), x;
else return ch[0][y] = merge(x, ch[0][y]), pushup(y), y;
} inline void insert(int v) { split(rt, v, a, b), rt = merge(a, merge(Newnode(v), b)); } inline void erase(int v) { split(rt, v, a, c), split(a, v - 1, a, b), b = merge(ch[0][b], ch[1][b]), rt = merge(a, merge(b, c)); } inline void build(int l, int r) { for (rg int i = l; i <= r; ++i) insert(A[i]); } inline int kth(int p, int k) {
if (siz[ch[0][p]] + 1 > k) return kth(ch[0][p], k);
if (siz[ch[0][p]] + 1 == k) return val[p];
if (siz[ch[0][p]] + 1 < k) return kth(ch[1][p], k - siz[ch[0][p]] - 1);
} inline int pre(int v) { split(rt, v - 1, a, b), c = a != 0 ? kth(a, siz[a]) : -INF, rt = merge(a, b); return c; } inline int nxt(int v) { split(rt, v, a, b), c = b != 0 ? kth(b, 1) : INF, rt = merge(a, b); return c; } inline int rank(int v) { split(rt, v - 1, a, b), c = siz[a] + 1, rt = merge(a, b); return c; }
} t[_ << 2]; inline int lc(int p) { return p << 1; } inline int rc(int p) { return p << 1 | 1; } inline void build(int p = 1, int l = 1, int r = n) {
t[p].build(l, r);
if (l == r) return ;
int mid = (l + r) >> 1;
build(lc(p), l, mid), build(rc(p), mid + 1, r);
} inline void update(int x, int v, int p = 1, int l = 1, int r = n) {
t[p].erase(A[x]), t[p].insert(v);
if (l == r) return ;
int mid = (l + r) >> 1;
if (x <= mid) update(x, v, lc(p), l, mid);
else update(x, v, rc(p), mid + 1, r);
} inline int rank(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
if (ql <= l && r <= qr) return t[p].rank(v) - 1;
int mid = (l + r) >> 1, res = 0;
if (ql <= mid) res += rank(ql, qr, v, lc(p), l, mid);
if (qr > mid) res += rank(ql, qr, v, rc(p), mid + 1, r);
return res;
} inline int kth(int ql, int qr, int k) {
int l = 0, r = 100000000, res;
while (l <= r) {
int mid = (l + r) >> 1;
if (rank(ql, qr, mid) + 1 <= k) res = mid, l = mid + 1; else r = mid - 1;
}
return res;
} inline int pre(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
if (ql <= l && r <= qr) return t[p].pre(v);
int mid = (l + r) >> 1, res = -INF;
if (ql <= mid) res = max(res, pre(ql, qr, v, lc(p), l, mid));
if (qr > mid) res = max(res, pre(ql, qr, v, rc(p), mid + 1, r));
return res;
} inline int nxt(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
if (ql <= l && r <= qr) return t[p].nxt(v);
int mid = (l + r) >> 1, res = INF;
if (ql <= mid) res = min(res, nxt(ql, qr, v, lc(p), l, mid));
if (qr > mid) res = min(res, nxt(ql, qr, v, rc(p), mid + 1, r));
return res;
} int main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(n), read(m);
for (rg int i = 1; i <= n; ++i) read(A[i]);
build();
for (rg int opt, l, r, k, x; m--; ) {
read(opt);
if (opt == 1) read(l), read(r), read(k), printf("%d\n", rank(l, r, k) + 1);
if (opt == 2) read(l), read(r), read(k), printf("%d\n", kth(l, r, k));
if (opt == 3) read(x), read(k), update(x, k), A[x] = k;
if (opt == 4) read(l), read(r), read(k), printf("%d\n", pre(l, r, k));
if (opt == 5) read(l), read(r), read(k), printf("%d\n", nxt(l, r, k));
}
return 0;
}

「luogu3380」【模板】二逼平衡树(树套树)的更多相关文章

  1. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  2. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  3. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  4. BZOJ3196 二逼平衡树 【线段树套平衡树】

    题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...

  5. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

  6. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

  7. [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

    传送门 至少BZOJ过了,其他的直接弃. 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的 ...

  8. [luogu3380][bzoj3196]【模板】二逼平衡树【树套树】

    题目地址 [洛谷传送门] 题目大意 区间查询k的排名,查找k排名的数,单点修改,区间前驱,区间后继. 感想 真的第一次写树套树,整个人都不对了.重构代码2次,发现样例都过不了,splay直接爆炸,可能 ...

  9. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

随机推荐

  1. c# 泛型<T>类型参数T的约束where

    在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制.如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误.这些限制称为约束.约束是使用 where 上 ...

  2. Java上传图片到Ftp,包含上传后文件大小为0的问题和Properties配置文件的读取

    准备工作:需要使用coomos-net jar包.下载地址 一. 上传图片到FTP,文件大小为0的问题,解决:将ftp模式修改为Passive模式就可以了. //将ftp模式修改为Passive模式 ...

  3. scw——03错误,swagger开启错误

    错误: 代码: @Value("${swagger2.enable:false}") private boolean enable = false; 原因:没有开启swagger的 ...

  4. rke安装k8s cluster配置

    rke安装k8s cluster配置 最简配置 cluster.yml nodes: - address: 192.168.0.103 user: lishikai role: [controlpla ...

  5. 用fgets()和fputs()代替gets()和puts()

    gets()和puts不安全,有些平台会报错,如pat. gets输入字符串时,不进行数组下标的检查,也就是说当你的数组长度是n时,输入超过该长度的字符串的时候,编译不会出错,但是运行的时候会出现数组 ...

  6. 安装Oracle进行先决条件检查时显示 Environment variable:"PATH" 失败”

    问题已解决:安装时exe可执行文件的目录也不能有中文,安装时注意目录一定要按oracle的格式.运行安装程序时,要用右键--> 要以管理员方式启动. 原文: 用到oracle数据库,由于电脑装的 ...

  7. 【网易官方】极客战记(codecombat)攻略-地牢-辐射光环

    关卡连接: https://codecombat.163.com/play/level/radiant-aura 骷髅,恐惧还是回避? 简介: 敬请期待! 默认代码 # 捡起发光石,让骷髅怪远离你一会 ...

  8. string常用成员函数

    string常用成员函数 std::string::clear Clear string Erases the contents of the string, which becomes an emp ...

  9. Jmeter注册100个账户的三个方法

    Jmeter注册账户比如注册成千上万个账户,如何快速实现呢? 三种方法分别举例注册5个账户 1)添加CSV data config_txt 2)添加CSV data config_csv 3)函数助手 ...

  10. vs rdlc 设置Tablix 在新页面重复表头

    设置方法: 1.选中Tablix控件 2.点开三角形 3.选择高级模式 4.在行组 下 选择静态,然后看右边的属性 5.将属性设置为如下 就可以让Tablix控件实现在新页中带表头