我想要打一个Splay

大规模单步调试现场
这里只提供模板,详细解说请参见这位大佬的题解。
PS:这位大佬的rank操作跑的飞飞飞飞飞慢,利用Find操作优化之后可以极大优化时间
PPS:这位大佬的ins操作里判空也有点问题,修改后有两种写法:
1.直接在开始时ins一个\(INF\)和一个\(-INF\)、之后3号操作找到的\(rank\)+1后输出,4号操作找排名为x+1的数。
2.把判空改为本人的样式

#include<cstdio>
#include<iostream>
#include<cmath>
#include<fstream>
#include<time.h>
using namespace std;
char *p1,*p2,buf[1<<20];
#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++)))
//#define GC getchar()
inline int in()
{
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch)){
        w|=ch=='-';
        ch=GC;
    }
    while(isdigit(ch)){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=GC;
    }
    return w?-x:x;
}
struct node{
    int id,f;
    int son[2];
    int size;
    int cnt;
};
const int maxn=200010;
struct tree{
    node t[maxn];
    int n,points;
    #define root t[0].son[1]
    void updata(int p){
        t[p].size=t[t[p].son[0]].size+t[t[p].son[1]].size+t[p].cnt;
    }
    int identify(int p)
    {
        return t[t[p].f].son[0]==p?0:1;
    }
    void connect(int p,int f,int son)
    {
        t[p].f=f;
        t[f].son[son]=p;
        return;
    }
    void rotate(int p)
    {
        int f=t[p].f;
        int ff=t[f].f;
        int fs=identify(f);
        int s=identify(p);
        int Os=t[p].son[s^1];
        connect(Os,f,s);
        connect(f,p,(s^1));
        connect(p,ff,fs);
        updata(f);
        updata(p);
    }
    void splay(int now,int to)
    {
        to=t[to].f;
        while(t[now].f!=to){
            int up=t[now].f;
            if(t[up].f==to)rotate(now);
            else {
                if(identify(up)==identify(now)){
                    rotate(up);
                    rotate(now);
                }
                else{
                    rotate(now);
                    rotate(now);
                }
            }
        }
    }
    int add_point(int val,int f){
        n+=1;
        t[n].id=val;
        t[n].f=f;
        t[n].cnt=t[n].size=1;
        return n;
    }
    void destroy(int p){
        t[p].cnt=t[p].f=t[p].id=t[p].size=t[p].son[1]=t[p].son[0]=0;
        if(p==n)n-=1;
    }
    int find(int val){
        int now=root;
        while(1){
            if(t[now].id==val){
                splay(now,root);
                return now;
            }
            int nex=val<t[now].id?0:1;
            if(!t[now].son[nex])return 0;
            now=t[now].son[nex];
        }
    }
    int ins(int val){
        points+=1;
        if(points==1){
            root=n+1;
            add_point(val,0);
            return 0;
        }
        int now=root;
        while(1){
            t[now].size+=1;
            if(val==t[now].id){
                t[now].cnt+=1;
                return now;
            }
            int nex=val<t[now].id?0:1;
            if(!t[now].son[nex]){
                add_point(val,now);
                t[now].son[nex]=n;
                return n;
            }
            now=t[now].son[nex];
        }
        splay(now,root);
        return 0;
    }
    void push(int val){
        int add=ins(val);
        splay(add,root);
    }
    void del(int val){
        int tar=find(val);
        if(!tar)return;
        points-=1;
        if(t[tar].cnt>1){
            t[tar].cnt-=1;
            t[tar].size-=1;
            return;
        }
        if(!t[tar].son[0]){
            root=t[tar].son[1];
            t[root].f=0;
        }
        else{
            int ls=t[tar].son[0];
            while(t[ls].son[1])ls=t[ls].son[1];
            splay(ls,t[tar].son[0]);
            int rs=t[tar].son[1];
            connect(rs,ls,1);
            connect(ls,0,1);
            updata(ls);
        }
        destroy(tar);
    }
    int rank(int val){
//        int res=0,now=root;
//        while(1){
//            if(t[now].id==val)return res+t[t[now].son[0]].size+1;
//            if(!now)return 0;
//            if(val<t[now].id)now=t[now].son[0];
//            else{
//                res+=t[t[now].son[0]].size+t[now].cnt;
//                now=t[now].son[1];
//            }
//        }
//        splay(now,root);
//        return 0;
        find(val);
        return t[t[root].son[0]].size+1;
    }
    int get_k(int val){
        if(val>points)return -23333333;
        int now=root;
        while(1){
            int tmp=t[now].size-t[t[now].son[1]].size;
            if(val>t[t[now].son[0]].size&&val<=tmp)break;
            if(val<tmp)now=t[now].son[0];
            else{
                val-=tmp;
                now=t[now].son[1];
            }
        }
        splay(now,root);
        return t[now].id;
    }
    int lower(int val)
    {
        int now=root;
        int res=-23333333;
        while(now){
            if(t[now].id<val&&t[now].id>res)res=t[now].id;
            if(val>t[now].id)now=t[now].son[1];
            else now=t[now].son[0];
        }
        return res;
    }
    int upper(int val)
    {
        int now=root;
        int res=23333333;
        while(now){
            if(t[now].id>val&&t[now].id<res)res=t[now].id;
            if(val<t[now].id)now=t[now].son[0];
            else now=t[now].son[1];
        }
        return res;
    }
    #undef root
}tr;
int n;
int main()
{
//  freopen("splay.in","r",stdin);
//  freopen("splay.out","w",stdout); 
//  clock_t st,fs;
//  st=clock();
//  ofstream fl("time.txt");
    n=in();
    int i;
//    tr.push(23333333);
//    tr.push(-23333333);
    for(i=1;i!=n+1;++i){
        int ch,x;
//        fs=clock();
//        fl<<fs-st<<endl;
        ch=in();x=in();
        switch(ch){
            case 1:{
                tr.push(x);
                break;
            }
            case 2:{
                tr.del(x);
                break;
            }
            case 3:{
                printf("%d\n",tr.rank(x));
                break;
            }
            case 4:{
                printf("%d\n",tr.get_k(x));
                break;
            }
            case 5:{
                printf("%d\n",tr.lower(x));
                break;
            }
            case 6:{
                printf("%d\n",tr.upper(x));
                break;
            }
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/cooper233/p/12000363.html