zoukankan      html  css  js  c++  java
  • 洛谷 P3369 【模板】普通平衡树

    洛谷 P3369 【模板】普通平衡树

    洛谷传送门

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入 xx
    2. 删除 xx 数(若有多个相同的数,因只删除一个)
    3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
    4. 查询排名为 xx 的数
    5. 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
    6. 求 xx 的后继(后继定义为大于 xx,且最小的数)

    输入格式

    第一行为 nn,表示操作的个数,下面 nn 行每行有两个数 ext{opt}opt 和 xx, ext{opt}opt 表示操作的序号( 1 leq ext{opt} leq 61≤opt≤6 )

    输出格式

    对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案

    说明/提示

    【数据范围】
    对于 100%100% 的数据,1le n le 10^51≤n≤105,|x| le 10^7∣x∣≤107

    来源:Tyvj1728 原名:普通平衡树

    在此鸣谢


    题解:

    题如其名。

    平衡树不会的请走这边:

    Treap详解

    Splay详解

    蒟蒻只学了两种平衡树qwq...蒟蒻太菜了。

    最后还是用SplayAC的:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    int n;
    int tot,root;
    int val[maxn],size[maxn],cnt[maxn],fa[maxn],ch[maxn][2];
    void maintain(int x)
    {
        size[x]=cnt[x]+size[ch[x][0]]+size[ch[x][1]];
    }
    int find(int x)
    {
        int pos=root;
        while(val[pos]!=x)
            pos=ch[pos][x>val[pos]];
        return pos;
    }
    int get(int x)
    {
        int f=fa[x];
        return ch[f][1]==x;
    }
    void rotate(int x)
    {
        int y=fa[x],z=fa[y];
        int k=get(x);//k表示x是y的什么儿子
        ch[y][k]=ch[x][k^1],fa[ch[y][k]]=y;
        ch[x][k^1]=y,fa[y]=x,fa[x]=z;
        if(z)
            ch[z][ch[z][1]==y]=x;
        maintain(y),maintain(x);
    }
    void splay(int x,int &goal)
    {
        int f=fa[goal];
        while(fa[x]!=f)
        {
            if(fa[fa[x]]!=f)
                rotate(get(x)==get(fa[x])?fa[x]:x);
            rotate(x);
        }
        goal=x;
    }
    void insert(int x)
    {
        if(!root)
        {
            ++tot;
            root=tot;
            val[root]=x;
            cnt[root]=1;
            maintain(root);
            return;
        }
        int pos,f;
        pos=f=root;
        while(pos && val[pos]!=x)
            f=pos,pos=ch[pos][x>val[pos]];
        if(!pos)
        {
            ++tot;
            cnt[tot]=1;
            val[tot]=x;
            fa[tot]=f;
            ch[f][x>val[f]]=tot;
            maintain(tot);
            splay(tot,root);
            return;
        }
        ++cnt[pos];
        maintain(pos);
        splay(pos,root);
    }
    void del(int x)
    {
        int pos=find(x);
        splay(pos,root);
        if(cnt[root]>1)
        {
            cnt[root]--;
            maintain(root);
            return;
        }
        if((!ch[root][0])&&(!ch[root][1]))
            root=0;
        else if(!ch[root][0])
            root=ch[root][1],fa[root]=0;
        else if(!ch[root][1])
            root=ch[root][0],fa[root]=0;
        else
        {
            pos=ch[root][0];
            while(ch[pos][1])
                pos=ch[pos][1];
            splay(pos,ch[root][0]);
            ch[pos][1]=ch[root][1];
            fa[ch[root][1]]=pos,fa[pos]=0;
            maintain(pos);
            root=pos;
        }
    }
    int rank(int x)
    {
        int pos=find(x);
        splay(pos,root);
        return size[ch[root][0]]+1;
    }
    int kth(int x)
    {
        int pos=root;
        while(1)
        {
            if(x<=size[ch[pos][0]])
                pos=ch[pos][0];
            else 
            {
                x-=(size[ch[pos][0]]+cnt[pos]);
                if(x<=0)
                {
                    splay(pos,root);
                    return val[pos];
                }
                pos=ch[pos][1];
            }
        }
    }
    int pre(int x)
    {
        int ans;
        int pos=root;
        while(pos)
        {
            if(x>val[pos])
            {
                ans=val[pos];
                pos=ch[pos][1];
            }
            else
                pos=ch[pos][0];
        }
        return ans;
    }
    int nxt(int x)
    {
        int ans;
        int pos=root;
        while(pos)
        {
            if(x<val[pos])
            {
                ans=val[pos];
                pos=ch[pos][0];
            }
            else
                pos=ch[pos][1];
        }
        return ans;
    }
    int main()
    {
        scanf("%d",&n);
        while(n--)
        {
            int opt,x;
            scanf("%d%d",&opt,&x);
            if(opt==1)
                insert(x);
            if(opt==2)
                del(x);
            if(opt==3)
                printf("%d
    ",rank(x));
            if(opt==4)
                printf("%d
    ",kth(x));
            if(opt==5)
                printf("%d
    ",pre(x));
            if(opt==6)
                printf("%d
    ",nxt(x));
        }
        return 0;
    }
    
  • 相关阅读:
    centos7上修改lv逻辑卷的大小
    centos6上调整lv逻辑卷
    nginx的日志配置
    修改Linux系统默认编辑器
    mysqldump命令的安装
    centos7上设置中文字符集
    nginx的80端口跳转到443
    ubuntu上安装docker和docker-compose
    javascript递归、循环、迭代、遍历和枚举概念
    Lattice 开发工具Diamond 相关版本下载地址
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13391495.html
Copyright © 2011-2022 走看看