zoukankan      html  css  js  c++  java
  • [模板]平衡树splay

    气死我了,调了一个下午+两节课,各种大大小小的错误,各种调QAQ,最后总之是调出来了.

    其实就是一个双旋操作,然后其他就是左儿子<当前节点<右儿子,剩下就是细节了.

    题干:

    题目描述
    
    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    
        插入xxx数
        删除xxx数(若有多个相同的数,因只删除一个)
        查询xxx数的排名(排名定义为比当前数小的数的个数+1+1+1。若有多个相同的数,因输出最小的排名)
        查询排名为xxx的数
        求xxx的前驱(前驱定义为小于xxx,且最大的数)
        求xxx的后继(后继定义为大于xxx,且最小的数)
    
    输入输出格式
    输入格式:
    
    第一行为nnn,表示操作的个数,下面nnn行每行有两个数optoptopt和xxx,optoptopt表示操作的序号( 1≤opt≤6 1 leq opt leq 6 1≤opt≤6 )
    
    输出格式:
    
    对于操作3,4,5,63,4,5,63,4,5,6每行输出一个数,表示对应答案
    
    输入输出样例
    输入样例#1: 复制
    
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    
    输出样例#1: 复制
    
    106465
    84185
    492737

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    #define pr pair<int,int>
    #define mp make_pair
    const int INF = 2147480000;
    const double eps = 1e-8;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    struct node
    {
        int v,fa,ch[3],sum,recy;
    }e[500005];
    int n,points,N;
    #define root e[0].ch[1]
    void update(int x)
    {
        e[x].sum = e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].recy;
    }
    int iden(int x)
    {
        return e[e[x].fa].ch[0] == x ? 0 : 1;
    }
    void connect(int x,int f,int son)
    {
        e[x].fa = f;
        e[f].ch[son] = x;
    }
    void rotate(int x)
    {
        int y = e[x].fa;
        int mroot = e[y].fa;
        int mrootson = iden(y);
        int yson = iden(x);
        int b = e[x].ch[yson ^ 1];
        connect(b,y,yson);
        connect(y,x,yson ^ 1);
        connect(x,mroot,mrootson);
        update(y);
        update(x);
    }
    void splay(int at,int to)
    {
        to = e[to].fa;
        while(e[at].fa != to)
        {
            int up = e[at].fa;
            if(e[up].fa == to) rotate(at);
            else if(iden(up) == iden(at))
            {
                rotate(up);
                rotate(at);
            }
            else
            {
                rotate(at);
                rotate(at);
            }
        }
    }
    int crepoint(int v,int fa)
    {
        n++;
        e[n].v = v;
        e[n].fa = fa;
        // cout<<v<<" "<<fa<<endl;
        e[n].sum = e[n].recy = 1;
        return n;
    }
    void destroy(int x)
    {
        e[x].v = e[x].ch[0] = e[x].ch[1] = e[x].sum = e[x].fa = e[x].recy = 0;
        if(x == n)
        n--;
        while(e[n].v == 0 && e[n].sum == 0 && n > 0)
        n--;
    }
    int find(int v)
    {
        int now = root;
        while(true)
        {
            if(e[now].v == v)
            {
                splay(now,root);
                return now;
            }
            int nxt = v < e[now].v ? 0 : 1;
            if(!e[now].ch[nxt]) return 0;
            now = e[now].ch[nxt];
        }
    }
    int build(int v)
    {
        points++;
        // cout<<v<<endl;
        if(n == 0)
        {
            root = 1;
            crepoint(v,0);
        }
        else
        {
            int now = root;
            while(true)
            {
                // cout<<now<<endl;
                e[now].sum++;
                if(v == e[now].v)
                {
                    e[now].recy++;
                    return now;
                }
                int nxt = v < e[now].v ? 0 : 1;
                if(!e[now].ch[nxt])
                {
                    crepoint(v,now);
                    e[now].ch[nxt] = n;
                    return n;
                }
                now = e[now].ch[nxt];
            }
        }
        return 0;
    }
    void push(int v)
    {
        int add = build(v);
        if( rand() % 20 == 1 )
            splay(add,root);
    }
    void pop(int v)
    {
        int deal = find(v);
        if(!deal) return;
        points--;
        if(e[deal].recy > 1)
        {
            e[deal].recy--;
            e[deal].sum--;
            return;
        }
        if(!e[deal].ch[0])
        {
            root = e[deal].ch[1];
            e[root].fa = 0;
        }
        else
        {
            int lef = e[deal].ch[0];
            while(e[lef].ch[1]) lef = e[lef].ch[1];
            splay(lef,e[deal].ch[0]);
            int rig = e[deal].ch[1];
            connect(rig,lef,1);connect(lef,0,1);
            update(lef);
        }
        destroy(deal);
    }
    int Rank(int v)
    {
        int ans = 0,now = root;
        // cout<<v<<endl;
        while(true)
        {
            if(e[now].v == v)
            return ans + e[e[now].ch[0]].sum + 1;
            if(now == 0) return 0;
            if(v < e[now].v) now = e[now].ch[0];
            else
            {
                ans = ans + e[e[now].ch[0]].sum + e[now].recy;
                now = e[now].ch[1];
            }
        }
        //if(now) splay(now,root);
        return 0;
    }
    int atRank(int x)
    {
        if(x > points) return -INF;
        int now = root;
        // cout<<root<<endl;
        while(true)
        {
            // cout<<now<<endl;
            int minused = e[now].sum - e[e[now].ch[1]].sum;
            if(x > e[e[now].ch[0]].sum && x <= minused) break;
            if(x < minused) now = e[now].ch[0];
            else
            {
                x = x - minused;
                now = e[now].ch[1];
            }
        }
        //splay(now,root);
        return e[now].v;
    }
    int upper(int v)
    {
        int now = root;
        int result = INF;
        while(now)
        {
            if(e[now].v > v && e[now].v < result) result = e[now].v;
            if(v < e[now].v) now = e[now].ch[0];
            else
            now = e[now].ch[1];
        }
        return result;
    }
    int lower(int v)
    {
        int now = root;
        int result = -INF;
        while(now)
        {
            // cout<<now<<endl;
            if(e[now].v < v && e[now].v > result)
            result = e[now].v;
            if(v > e[now].v) now = e[now].ch[1];
            else
            now = e[now].ch[0];
        }
        return result;
    }
    void Szcheck( int pos ){
        if( e[pos].ch[0] ) Szcheck(e[pos].ch[0]);
        if( e[pos].ch[1] ) Szcheck(e[pos].ch[1]);
        if( e[e[pos].ch[0]].sum + 1 + e[e[pos].ch[1]].sum != e[pos].sum ){
            cout << "Size Error At Pos" << pos << endl;
        }
    }
    void gg()
    {
        cout<<n<<endl;
        duke(i,1,n)
        {
            printf("%d ",e[i].v);
        }
        puts("");
    }
    int main()
    {
        // freopen("3369.in","r",stdin);
        read(N);
        duke(i,1,N)
        {
            int opt,value;
            // cout<<endl<<i<<endl;
            read(opt);read(value);
            // if(opt != 1 && opt != 2)
            // cout<<opt<<" "<<value<<endl;
            switch(opt)
            {
                case 1 : push(value);break;
                case 2 : pop(value);break;
                case 3 : cout<<Rank(value)<<endl;break;
                case 4 : {cout<<atRank(value)<<endl;}break;
                case 5 : cout<<lower(value)<<endl;break;
                case 6 : cout<<upper(value)<<endl;break;
                case 7 : gg();
            }
            //Szcheck(root);
            // cout<<i<<endl;
        }
        return 0;
    }
    /*
    10
    1 106465
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    4 1
    */

    代码有点长...

  • 相关阅读:
    SpringMVC 高级开发(异常页面处理,json传输数据,文件上传)
    SpringMVC中的Controller方法的(返回值/参数类型)
    SpringMVC的其他注解
    SpringMVC的整合,基于注解
    SpringMVC入门程序:helloWorld
    SpringMVC入门
    SpringAOP事务的实现
    仅需三步,即可在Vue项目中配置sass
    前端常用的设计模式
    call和apply的区别及其用法
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10030333.html
Copyright © 2011-2022 走看看