zoukankan      html  css  js  c++  java
  • hiho #1329 : 平衡树·Splay

    #1329 : 平衡树·Splay

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Ho:小Hi,上一次你跟我讲了Treap,我也实现了。但是我遇到了一个关键的问题。

    小Hi:怎么了?

    小Ho:小Hi你也知道,我平时运气不太好。所以这也反映到了我写的Treap上。

    小Hi:你是说你随机出来的权值不太好,从而导致结果很差么?

    小Ho:就是这样,明明一样的代码,我的Treap运行结果总是不如别人。小Hi,有没有那种没有随机因素的平衡树呢?

    小Hi:当然有了,这次我就跟你讲讲一种叫做Splay的树吧。而且Splay树能做到的功能比Treap要更强大哦。

    小Ho:那太好了,你快告诉我吧!

    提示:Splay

    输入

    第1行:1个正整数n,表示操作数量,100≤n≤200,000

    第2..n+1行:可能包含下面3种规则:

    1个字母'I',紧接着1个数字k,表示插入一个数字k到树中,1≤k≤1,000,000,000,保证每个k都不相同

    1个字母'Q',紧接着1个数字k。表示询问树中不超过k的最大数字

    1个字母'D',紧接着2个数字a,b,表示删除树中在区间[a,b]的数。

    输出

    若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解

    样例输入
    6
    I 1
    I 2
    I 3
    Q 4
    D 2 2
    Q 2
    样例输出
    3
    1

    不会就套板子;

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-14
    const int N=1e5+10,MAXN=1e6+10,inf=2147483647;
    const ll INF=1e18+10,mod=2147493647;
    int cnt, rt;
    int Add[MAXN];
    struct Tree{
        int key, num, size, fa, son[2];
    }T[MAXN];
    inline void PushUp(int x)
    {
        T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].num;
    }
    inline void PushDown(int x)
    {
        if(Add[x])
        {
            if(T[x].son[0])
            {
                T[T[x].son[0]].key+=Add[x];
                Add[T[x].son[0]]+=Add[x];
            }
            if(T[x].son[1])
            {
                T[T[x].son[1]].key+=Add[x];
                Add[T[x].son[1]]+=Add[x];
            }
            Add[x]=0;
        }
    }
    
    inline int Newnode(int key, int fa) //新建一个节点并返回
    {
        ++cnt;
        T[cnt].key=key;
        T[cnt].num=T[cnt].size=1;
        T[cnt].fa=fa;
        T[cnt].son[0]=T[cnt].son[1]=0;
        return cnt;
    }
    
    inline void Rotate(int x, int p) //0左旋 1右旋
    {
        int y=T[x].fa;
        PushDown(y);
        PushDown(x);
        T[y].son[!p]=T[x].son[p];
        T[T[x].son[p]].fa=y;
        T[x].fa=T[y].fa;
        if(T[x].fa)
            T[T[x].fa].son[T[T[x].fa].son[1] == y]=x;
        T[x].son[p]=y;
        T[y].fa=x;
        PushUp(y);
        PushUp(x);
    }
    
    void Splay(int x, int To) //将x节点移动到To的子节点中
    {
        while(T[x].fa != To)
        {
            if(T[T[x].fa].fa == To)
                Rotate(x, T[T[x].fa].son[0] == x);
            else
            {
                int y=T[x].fa, z=T[y].fa;
                int p=(T[z].son[0] == y);
                if(T[y].son[p] == x)
                    Rotate(x, !p), Rotate(x, p); //之字旋
                else
                    Rotate(y, p), Rotate(x, p); //一字旋
            }
        }
        if(To == 0) rt=x;
    }
    int GetPth(int p, int To) //返回第p小的节点 并移动到To的子节点中
    {
        if(!rt || p > T[rt].size) return 0;
        int x=rt;
        while(x)
        {
            PushDown(x);
            if(p >= T[T[x].son[0]].size+1 && p <= T[T[x].son[0]].size+T[x].num)
                break;
            if(p > T[T[x].son[0]].size+T[x].num)
            {
                p-=T[T[x].son[0]].size+T[x].num;
                x=T[x].son[1];
            }
            else
                x=T[x].son[0];
        }
        Splay(x, 0);
        return x;
    }
    
    int Find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
    {
        if(!rt) return 0;
        int x=rt;
        while(x)
        {
            PushDown(x);
            if(T[x].key == key) break;
            x=T[x].son[key > T[x].key];
        }
        if(x) Splay(x, 0);
        return x;
    }
    
    int Prev() //返回根节点的前驱 非重点
    {
        if(!rt)return 0;
        if(T[rt].num>1) return rt;
        if(!rt || !T[rt].son[0]) return 0;
        int x=T[rt].son[0];
        while(T[x].son[1])
        {
            PushDown(x);
            x=T[x].son[1];
        }
        Splay(x, 0);
        return x;
    }
    
    int Succ() //返回根结点的后继 非重点
    {
        if(!rt || !T[rt].son[1]) return 0;
        int x=T[rt].son[1];
        while(T[x].son[0])
        {
            PushDown(x);
            x=T[x].son[0];
        }
        Splay(x, 0);
        return x;
    }
    void Insert(int key) //插入key值
    {
        if(!rt)
            rt=Newnode(key, 0);
        else
        {
            int x=rt, y=0;
            while(x)
            {
                PushDown(x);
                y=x;
                if(T[x].key == key)
                {
                    T[x].num++;
                    T[x].size++;
                    break;
                }
                T[x].size++;
                x=T[x].son[key > T[x].key];
            }
            if(!x)
                x=T[y].son[key > T[y].key]=Newnode(key, y);
            Splay(x, 0);
        }
    }
    
    void Delete(int key) //删除值为key的节点1个
    {
        int x=Find(key);
        if(!x) return;
        if(T[x].num>1)
        {
            T[x].num--;
            PushUp(x);
            return;
        }
        int y=T[x].son[0];
        while(T[y].son[1])
            y=T[y].son[1];
        int z=T[x].son[1];
        while(T[z].son[0])
            z=T[z].son[0];
        if(!y && !z)
        {
            rt=0;
            return;
        }
        if(!y)
        {
            Splay(z, 0);
            T[z].son[0]=0;
            PushUp(z);
            return;
        }
        if(!z)
        {
            Splay(y, 0);
            T[y].son[1]=0;
            PushUp(y);
            return;
        }
        Splay(y, 0);
        Splay(z, y);
        T[z].son[0]=0;
        PushUp(z);
        PushUp(y);
    }
    
    int GetRank(int key) //获得值<=key的节点个数
    {
        if(!Find(key))
        {
            Insert(key);
            int tmp=T[T[rt].son[0]].size;
            Delete(key);
            return tmp;
        }
        else
            return T[T[rt].son[0]].size+T[rt].num;
    }
    
    void Delete(int l, int r) //删除值在[l, r]中的所有节点 l!=r
    {
        if(l>r)return;
        if(!Find(l)) Insert(l);
        int p=Prev();
        if(!Find(r)) Insert(r);
        int q=Succ();
        if(!p && !q)
        {
            rt=0;
            return;
        }
        if(!p)
        {
            T[rt].son[0]=0;
            PushUp(rt);
            return;
        }
        if(!q)
        {
            Splay(p, 0);
            T[rt].son[1]=0;
            PushUp(rt);
            return;
        }
        Splay(p, q);
        T[p].son[1]=0;
        PushUp(p);
        PushUp(q);
    }
    char str[N];
    int main()
    {
        int n;
        scanf("%d",&n);
        while(n--)
        {
            int l,r;
            scanf("%s%d",str,&l);
            if(str[0]=='I')
                Insert(l);
            else if(str[0]=='Q')
            {
                Insert(l);
                printf("%d
    ",T[Prev()].key);
                Delete(l);
            }
            else
            {
                scanf("%d",&r);
                Delete(l,r);
            }
        }
        return 0;
    }

    #1329 : 平衡树·Splay

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Ho:小Hi,上一次你跟我讲了Treap,我也实现了。但是我遇到了一个关键的问题。

    小Hi:怎么了?

    小Ho:小Hi你也知道,我平时运气不太好。所以这也反映到了我写的Treap上。

    小Hi:你是说你随机出来的权值不太好,从而导致结果很差么?

    小Ho:就是这样,明明一样的代码,我的Treap运行结果总是不如别人。小Hi,有没有那种没有随机因素的平衡树呢?

    小Hi:当然有了,这次我就跟你讲讲一种叫做Splay的树吧。而且Splay树能做到的功能比Treap要更强大哦。

    小Ho:那太好了,你快告诉我吧!

    提示:Splay

    输入

    第1行:1个正整数n,表示操作数量,100≤n≤200,000

    第2..n+1行:可能包含下面3种规则:

    1个字母'I',紧接着1个数字k,表示插入一个数字k到树中,1≤k≤1,000,000,000,保证每个k都不相同

    1个字母'Q',紧接着1个数字k。表示询问树中不超过k的最大数字

    1个字母'D',紧接着2个数字a,b,表示删除树中在区间[a,b]的数。

    输出

    若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解

    样例输入
    6
    I 1
    I 2
    I 3
    Q 4
    D 2 2
    Q 2
    样例输出
    3
    1
  • 相关阅读:
    MediaRecorder.AudioSource参数
    putty连接服务器
    支持库
    ImageView
    .net下MD5算法和加盐
    SqlHelper文件复习
    .net下连接数据库
    Windows Server 2003 R2 64位简体中文版下载
    gacutil.exe 注册assembly
    Sharepoint Powershell
  • 原文地址:https://www.cnblogs.com/jhz033/p/6248556.html
Copyright © 2011-2022 走看看