mark:pb_ds 普通平衡树
#include <bits/extc++.h>
#include <cstdio>
#define inf 998244353
using namespace __gnu_pbds;
using pai = std::pair<int, int> ;
tree <pai, null_type, std::less<pai>, rb_tree_tag, tree_order_statistics_node_update> tr;
int read(){
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x * f;
}
void write(int x){
if(x < 0) {putchar('-'); x = -x;}
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
int n, m;
int main(){
n = read(); tr.insert({inf, inf}); tr.insert({-inf, -inf});
int cnt = 0; pai tmp;
while(n--){
int op, x;
op = read(); x = read();
if(op == 1) tr.insert({x, ++cnt});
if(op == 2) tr.erase(tr.lower_bound({x, 0}));
if(op == 3) write(tr.order_of_key(*tr.lower_bound({x, 0}))), putchar('\n');
if(op == 4) write(tr.find_by_order(x) -> first), putchar('\n');
if(op == 5) write((--tr.lower_bound({x, 0})) -> first), putchar('\n');
if(op == 6) write(tr.upper_bound({x, inf}) -> first), putchar('\n');
}
}
翻最优解时看到一个好优美的封装平衡树
#include <algorithm>
//#include <cmath>
#include <cstdio>
#include <vector>
const int INF = (1 << 30);
const int Q = 100005; ///< 平衡树元素个数
const int MAXX = 10000000; ///< 元素最大值
const int T = MAXX; ///< 当元素有负数时,要把它转为正数,即加上一个数,一般为max(abs(x)) = T
const int P = 4472; ///< 分块块数,当前请设为int(sqrt(MAXX + T))
const int PP = (MAXX + T) / P; ///< 每块大小,20000000 = 最大值 + T
using namespace std;
#define rg register int
char buf[1 << 23], *p1 = buf, *p2 = buf;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline bool ig(char c) { return c >= 48 && c <= 57; }
inline void read(int& oi) {
char c;
int f = 1, res = 0;
while (c = gc(), (!ig(c)) && c ^ '-')
;
c ^ '-' ? res = (c ^ 48) : f = -1;
while (c = gc(), ig(c)) res = res * 10 + (c ^ 48);
oi = f * res;
}
inline void print(int oi) {
if (oi < 0) putchar('-'), oi = ~oi + 1;
if (oi > 9) print(oi / 10);
putchar(oi % 10 + 48);
}
int n;
/**
* @brief 用std::vector实现的小平衡树
*/
struct Vector {
vector<int> v; ///< 平衡树主体
vector<int>::iterator it; ///< 用来访问
// int sze; ///< 大小
/**
* @brief 向平衡树中加入一个数x
* @param x 要加入的数
* @return null
*/
inline void Insert(int x) {
it = lower_bound(v.begin(), v.end(), x);
v.insert(it, x);
}
/**
* @brief 在平衡树中删除一个数x
* @param x 要删除的数
* @return null
*/
inline void Delete(int x) {
it = lower_bound(v.begin(), v.end(), x);
v.erase(it);
}
/**
* @brief 求出x在平衡树中的排名,最小的数为第一名
* @param x 要求排名的数
* @return 排名
*/
inline int rank(int x) { return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; }
/**
* @brief 求出排名为x的数
* @param x 排名x
* @return 排名为x的数
*/
inline int kth(int x) { return v[x - 1]; }
/**
* @brief 求出x的前驱,若没有前驱返回0
* @param x 要求前驱的数
* @return x的前驱
*/
inline int pre(int x) {
it = lower_bound(v.begin(), v.end(), x);
return it == v.begin() ? 0 : (*(--it));
}
/**
* @brief 求出x的后续,若没有后续返回0
* @param x 要求后续的数
* @return x的后续
*/
inline int suf(int x) {
it = upper_bound(v.begin(), v.end(), x);
return it == v.end() ? 0 : (*it);
}
inline int min() { return !v.empty() ? suf(-INF) : 0; } ///<平衡树中的最小值
inline int max() { return !v.empty() ? pre(INF) : 0; } ///<平衡树中的最大值
};
Vector V[P + 1]; ///< 块,V[0]是块的平衡树
/**
* 最终的平衡树,分块实现,优化时间复杂度
*/
struct Devide {
int g[P + 1]; ///< 树状数组,维护sze
/**
* 将[x,P]中的数都加上y
* @param x 左边界
* @param y 加数
*/
inline void addd(int x, int y) {
for (rg i = x; i <= P; i += i & -i) g[i] += y;
}
/**
* 求出[1,x]的和
* @param x 右边界
* @return 和
*/
inline int qrry(int x) {
int res = 0;
for (rg i = x; i > 0; i -= i & -i) res += g[i];
return res;
}
/**
* 给[l,r]加上x
* @param l 左边界
* @param r 右边界
* @param x 加数
*/
inline void mddy(int l, int r, int x) {
if (!l || !r || l > r) return;
addd(l, x); // [l,P]加上x
addd(r + 1, -x); //[r+1,P]减去x
}
int sze[P + 1]; ///< 每个块的元素个数
#define bl(x) ((x - 1) / PP + 1) ///< 求出x在第几个数
/**
* 插入一个数
* @param x 要插入的数
*/
inline void Insert(int x) {
x += T; // 离散化
int blx = bl(x); // 求出x在哪个块
if (!sze[blx]) V[0].Insert(blx); // if(x==10543785){printf("%d\n",blx);system("pause");} // 如果之前没有这个块,就新建这个块
++sze[blx]; // 块内的元素个数++
mddy(blx, P, 1); // 对g进行更新
V[blx].Insert(x); // 块内插入
}
/**
* 删除一个数
* @param x 要删除的数
*/
inline void Delete(int x) {
x += T; // 离散化
int blx = bl(x); // 求出x是在哪个块
--sze[blx]; // 块元素--
if (!sze[blx]) V[0].Delete(blx); // 如果删掉这个块之后,块已经没有元素,删除这个块
mddy(blx, P, -1); // 对g进行更新
V[blx].Delete(x); // 块内删除
}
/**
* 已知排名,求元素
* @param x 排名
* @return 元素
*/
inline int kth(int x) {
int L = 1, R = P; ///< L:左边界 R:右边界
while (L < R) { // 双端闭区间,二分求第一个总元素个数>=x
int mid = L + R >> 1; // 取中值
int tim = qrry(mid); // 求出[1,mid]的块的元素个数
if (tim >= x) R = mid; // 如果可行,则>mid的肯定不是最优
else L = mid + 1; // 如果不可行,则<=mid的肯定都不可行
}
return V[L].kth(x - qrry(L - 1)) - T; // x - qrry(L - 1) 求出在块内的排名,-T 把离散化转换回来
}
/**
* 已知元素,求排名
* @param x 元素
* @return 排名
*/
inline int rank(int x) {
x += T; // 离散化
int blx = bl(x); // 求出x是在哪个块
int res = qrry(blx - 1); // 求出前面的块的元素个数
return res + V[blx].rank(x);
}
/**
* 求前驱,没有前驱返回0
* @param x 要求前驱的元素
* @return 前驱
* @retval 0 没有前驱
*/
inline int pre(int x) {
x += T; // 离散化
int blx = bl(x); // 求出x是在哪个块
int tim = (V[blx].pre(x)) - T; // 组内前驱
if (tim ^ -T) return tim; // 如果组内有前驱,返回前驱
int ls = V[0].pre(blx); // 否则,求出组的前驱
if (ls) return V[ls].max() - T; // 组的前驱的最大值
return 0;
}
/**
* 求后续,没有后续返回0
* @param x 要求后续的元素
* @return 后续
* @return 0 没有后续
*/
inline int suf(int x) {
x += T; // 离散化
int blx = bl(x); // 求出x是在哪个块
int tim = (V[blx].suf(x)) - T; // 组内后续
if (tim ^ -T) return tim; // 如果组内有后续,返回后续
int rs = V[0].suf(blx); // 否则,求出组的后续
if (rs) return V[rs].min() - T; // 组的后续的最大值
return 0;
}
} D;
int main() {
read(n);
while (n--) {
int opt, x;
read(opt);
read(x);
switch (opt) {
case 1: D.Insert(x); break;
case 2: D.Delete(x); break;
case 3:
print(D.rank(x));
putchar('\n');
break;
case 4:
print(D.kth(x));
putchar('\n');
break;
case 5:
print(D.pre(x));
putchar('\n');
break;
case 6:
print(D.suf(x));
putchar('\n');
break;
}
}
return 0;
}
作者:purplevine
出处:https://www.cnblogs.com/purplevine/p/16924290.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
本文来自博客园,作者:purplevine,转载请注明原文链接:https://www.cnblogs.com/purplevine/p/16924290.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探