Splay球调
查看原帖
Splay球调
344405
曹操废了楼主2022/4/6 22:32

RT,貌似死循环了

#include<iostream>
#include<cstdio>
#define MAXN 100001
#define INF 0x3f3f3f3f
#define root tree[0].ch[1]
using namespace std;
struct node{
    int val;//权值
    int fa;//父亲节点
    int ch[2];//0代表左儿子,1代表右儿子
    int rec;//这个权值的节点出现的次数
    int sum;//子节点的数量
}tree[MAXN];
int tot=0,pointnum=0,n;
bool ident(int x){//判断当前结点是左孩子,还是右孩子。0为左孩子,1为右孩子
    return tree[tree[x].fa].ch[0]=x?0:1;
}
void connect(int x,int fa,int how){//x节点将成为fa节点的how孩子
    tree[x].fa=fa;
    tree[fa].ch[how]=x;
}
void update(int x){
    tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
void rotate(int x){//单旋
    int Y=tree[x].fa;
    int R=tree[Y].fa;
    int Yson=ident(x);
    int Rson=ident(Y);
    int B=tree[x].ch[Yson^1];
    connect(B,Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
    update(Y);
    update(x);
}
void Splay(int x,int to){//双旋
    to=tree[to].fa;
    while(tree[x].fa!=to){
        if(tree[tree[x].fa].fa==to) rotate(x);
        else if(ident(x)==ident(tree[x].fa)) rotate(tree[x].fa),rotate(x);
        else rotate(x);rotate(x);
    }
}
int newpoint(int v,int f){//插入
    tree[++tot].fa=f;
    tree[tot].val=v;
    tree[tot].sum=tree[tot].rec=1;
    return tot;
}
void Insert(int x){//插入
    int now=root;
    if(root==0){
        newpoint(x,0);
        root=tot;
    }else{
        while(1){
            tree[now].sum++;
            if(tree[now].val==x){
                tree[now].rec++;
                Splay(now,root);
                return ;
            }
            int nxt=x<tree[now].val?0:1;
            if(!tree[now].ch[nxt]){
                int p=newpoint(x,now);
                tree[now].ch[nxt]=p;
                Splay(p,root);
                return ;
            }
            now=tree[now].ch[nxt];
        }
    }
}
int find(int v){//查询位置
    int now=root;
    while(1){
        if(tree[now].val==v){
            Splay(now,root);
            return now;
        }
        int nxt=v<tree[now].val?0:1;
        if(!tree[now].ch[nxt]) return 0;
        now=tree[now].ch[nxt];
    }
}
void dele(int x){//删除
    tree[x].sum=tree[x].val=tree[x].rec=tree[x].fa=tree[x].ch[0]=tree[x].ch[1];
    if(x==tot) tot--;
}
/*int rak(int v){// 查询值为v的数的排名
    int pos=find(v);
    return tree[tree[pos].ch[0]].sum+1;
}
*/
int rak(int v)// 查询值为v的数的排名 
{
    int ans=0,now=root;
    while(1)
    {
        if(tree[now].val==v)    return ans+tree[tree[now].ch[0]].sum+1;
        if(now==0)  return 0;
        if(v<tree[now].val)    now=tree[now].ch[0];
        else                 ans+=tree[tree[now].ch[0]].sum+tree[now].rec,now=tree[now].ch[1];
    }
    if(now)    Splay(now,root);
    return 0;
}
int arank(int x){//查询排名为x的数是什么 
    int now=root;
    while(1){
        int used=tree[now].sum-tree[tree[now].ch[1]].sum;
        if(x>tree[tree[now].ch[0]].sum&&x<=used) break;
        if(x<used) now=tree[now].ch[0];
        else x=x-used,now=tree[now].ch[1];
    }
    Splay(now,root);
    return tree[now].val;
}
int lower(int v){//查询v的前驱
    int now=root;
    int ans=-INF;
    while(now){
        if(tree[now].val<v&&tree[now].val>ans) ans=tree[now].val;
        if(v>tree[now].val) now=tree[now].ch[1];
        else now=tree[now].ch[0];
    }
    return ans;
}
int upper(int v){//查询v的后继
    int now=root;
    int ans=INF;
    while(now){
        if(tree[now].val>v&&tree[now].val<ans) ans=tree[now].val;
        if(v<tree[now].val) now=tree[now].ch[0];
        else now=tree[now].ch[1];
    }
    return ans;
}
int opt,x;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>opt>>x;
        if(opt==1){
            Insert(x);
        }
        if(opt==2){
            dele(x);
        }
        if(opt==3){
            printf("%d \n",rak(x));
        }
        if(opt==4){
            printf("%d \n",arank(x));
        }
        if(opt==5){
            printf("%d \n",lower(x));
        }
        if(opt==6){
            printf("%d \n",upper(x));
        }
    }
    return 0;
}

照着这篇博客打的

2022/4/6 22:32
加载中...