【模板】Splay (仅代码纯享版)
#include<cstdio> #include<algorithm> #define lson(x) tr[x].ch[0] #define rson(x) tr[x].ch[1] #define fa(x) tr[x].fa using namespace std; const int MAXN = 1e5 + 10; const int INF = 2147483647; int n; inline 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 << 1) + (x << 3) + (c ^ 48); c = getchar(); } return x * f; } struct Splay{ int tot, root; struct Tree{ int fa; //父节点 int val; //权值 int num; //这个权值的节点出现的个数 int size; //子节点的数量 int ch[2]; //ch[0] 左孩子,ch[1] 右孩子 Tree(){ fa = val = num = size = 0; ch[0] = ch[1] = 0; } }tr[MAXN]; Splay(){ tot = root = 0; } void Pushup(int rt){ //更新 tr[rt].size = tr[lson(rt)].size + tr[rson(rt)].size + tr[rt].num; } int Get_son(int rt){ //如果是右儿子,返回一,左儿子返回0 return rt == rson(fa(rt)) ? 1 : 0; } void Connect(int rt, int fa, int d){ tr[fa].ch[d] = rt; fa(rt) = fa; } void Rotate(int rt){ //旋转节点 rt 到他父亲的位置 int fa = fa(rt); // rt 的父亲 int gr_fa = fa(fa); // rt 的祖父 int d1 = Get_son(rt); // rt 是 fa 的哪一个孩子 int d2 = Get_son(fa); // fa 是 gr_fa 的哪一个孩子 Connect(tr[rt].ch[d1 ^ 1], fa, d1); Connect(fa, rt, d1 ^ 1); Connect(rt, gr_fa, d2); Pushup(fa); Pushup(rt); //这样,rt 就成功越位,晋升成了他祖父的儿子,他跌成了他的儿子(超级加倍) } //revolve 也是旋转的意思,因为 Splay 命名结构体了,Rotate 也用过了 void Revolve(int rt, int goal){ //将 rt 旋转到 goal goal = fa(goal); while(fa(rt) != goal){ if(fa(fa(rt)) == goal) Rotate(rt); else if(Get_son(rt) == Get_son(fa(rt))){ //函数名一定要有区分度,Get_son 和 Get 的区别,还有,封装在结构体里边他不报错啊 Rotate(fa(rt)); Rotate(rt); } else{ Rotate(rt); Rotate(rt); } } if(goal == 0){ root = rt; Connect(rt, 0, 1); } } void Build(int val, int fa, int d){//新建一个权值为val,是 fa 结点的 d 孩子的结点 int rt = ++tot; tr[rt].fa = fa; tr[rt].val = val; tr[rt].num = tr[rt].size = 1; tr[fa].ch[d] = rt; } void Insert(int val){ //插入一个值 if(root == 0){ Build(val, 0, 1); root = tot; return; } int rt = root; while(1){ tr[rt].size++; if(val == tr[rt].val){ tr[rt].num++; Revolve(rt, root); return; } int d = tr[rt].val < val ? 1 : 0; int son = tr[rt].ch[d]; if(!son){ Build(val, rt, d); Revolve(tot, root); return; } rt = son; } } int Get(int val){ int rt = root; while(1){ if(!rt) return 0; if(tr[rt].val == val){ Revolve(rt, root); return rt; } int d = tr[rt].val < val ? 1 : 0; int son = tr[rt].ch[d]; rt = son; } } void Delete(int val){ int rt = Get(val); if(!rt) return; if(tr[rt].num > 1){ tr[rt].num--; tr[rt].size--; return; } if(!lson(rt) && !rson(rt)) root = 0; else if(!lson(rt)){ root = rson(root); tr[root].fa = 0; } else if(!rson(rt)){ root = lson(root); tr[root].fa = 0; } else{ int pos = lson(rt); while(rson(pos)) pos = rson(pos); Revolve(pos, root); Connect(rson(rt), pos, 1); Pushup(pos); } } int Rank(int val){ int rt = root, ans = 0; while(rt){ if(tr[rt].val == val){ Revolve(rt, root); return tr[lson(rt)].size + 1; } if(tr[rt].val < val){ ans = ans + tr[lson(rt)].size + tr[rt].num; rt = rson(rt); } else rt = lson(rt); } return ans + 1; } int Find(int pos){ int rt = root; while(1){ int used = tr[rt].size - tr[rson(rt)].size; if(pos > tr[lson(rt)].size && pos <= used) break; if(pos >= used){ pos -= used; rt = rson(rt); } else rt = lson(rt); } Revolve(rt, root); return tr[rt].val; } int Pre(int val){ int rt = root; int ans = -INF; while(rt){ if(tr[rt].val < val && tr[rt].val > ans) ans = tr[rt].val; if(tr[rt].val < val) rt = rson(rt); else rt = lson(rt); } return ans; } int Suf(int val){ int rt = root; int ans = INF; while(rt){ if(tr[rt].val > val && tr[rt].val < ans) ans = tr[rt].val; if(tr[rt].val > val) rt = lson(rt); else rt = rson(rt); } return ans; } }S; int main(){ n = read(); for(register int i = 1; i <= n; i++){ int opt, x; opt = read(), x = read(); if(opt == 1) S.Insert(x); else if(opt == 2) S.Delete(x); else if(opt == 3) printf("%d\n", S.Rank(x)); else if(opt == 4) printf("%d\n", S.Find(x)); else if(opt == 5) printf("%d\n", S.Pre(x)); else if(opt == 6) printf("%d\n", S.Suf(x)); } return 0; }
以下为博客签名,与博文无关。
只要你们不停下来,那前面就一定有我。所以啊,不要停下来~
本文来自博客园,作者:TSTYFST,转载请注明原文链接:https://www.cnblogs.com/TSTYFST/p/16548861.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理