【模板】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