zoukankan      html  css  js  c++  java
  • 平衡树 fhqTreap

    //Treap fhq版(不旋转) 
    //所有操作依靠split()(分离)和merge()(合并)完成 
    //可支持区间操作和可持久化 比普通Treap更通用 
    //所有Treap中序遍历均为递增序列 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    int n,cnt,size,root,x,y,z;
    //x为小Treap的根节点 y为中Treap的根节点 z为大Treap的根节点 root为总Treap的根节点 
    int son[100001][2],siz[100001],val[100001],rd[100001];
    //左右儿子,子树大小+自己大小,点值,随机权值 
    int new_node(int m)//建立新节点 
    {
        siz[++size]=1;
        val[size]=m;
        rd[size]=rand();
        return size;
    }
    void update(int now)
    {
        siz[now]=siz[son[now][0]]+siz[son[now][1]]+1;
    }
    void split(int now,int k,int &a,int &b)
    {
        if(!now)
        {
            a=b=0;
            return;
        }
        if(val[now]<=k)
            a=now,split(son[now][1],k,son[now][1],b);
            //将此节点及其左子树接到小Treap上,并遍历此节点的右节点 
        else b=now,split(son[now][0],k,a,son[now][0]);
            //将此节点及其右子树接到大Treap上,并遍历此节点的左节点 
        update(now);
    }
    int merge(int a,int b)
    {
        if(!a||!b)
            return a+b;
        if(rd[a]<rd[b])
        {
            son[a][1]=merge(son[a][1],b);
            //将小Treap节点及其左子树接在总Treap上,并遍历此节点的右节点 
            update(a);
            return a; 
        }
        else
        {
            son[b][0]=merge(a,son[b][0]);
            //将大Treap节点及其右子树接在总Treap上,并遍历此节点的左节点 
            update(b);
            return b;
        }
    }
    int k_th(int now,int k)
    {
        while(1)
        {
            if(k<=siz[son[now][0]])
                now=son[now][0];
            else if(k==siz[son[now][0]]+1)
                return now;
            else
            {
                k-=siz[son[now][0]]+1;
                now=son[now][1];
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int u,k;
            scanf("%d%d",&u,&k);
            if(u==1)//插入 
            {
                split(root,k,x,z);//先分成两个Treap 此时k(若有)在小Treap中 
                root=merge(merge(x,new_node(k)),z);//重新合并 
            }
            if(u==2)//删除 
            {
                split(root,k,x,z);//先分成两个Treap 此时k在小Treap中 
                split(x,k-1,x,y);//再把小Treap分成两个Treap 此时k在中Treap中 且为中Treap根节点 
                y=merge(son[y][0],son[y][1]);//把中Treap根节点的两个子树合并 此时已删除k 
                root=merge(merge(x,y),z);//重新合并 
            }
            if(u==3)//查找权值为k的排名
            {
                split(root,k-1,x,z);//先分成两个Treap 此时小Treap中包含了所有小于k的数 
                printf("%d
    ",siz[x]+1);//k的排名即为小于k的权值数目+1 
                root=merge(x,z);//重新合并 
            }
            if(u==4)//查找排名为k的权值 
                printf("%d
    ",val[k_th(root,k)]);//直接输出 
            if(u==5)//求前驱 
            {
                split(root,k-1,x,z);//先分成两个Treap 此时k是大Treap中最小的数 
                printf("%d
    ",val[k_th(x,siz[x])]);//前驱即为小Treap中最大的数 即最右节点 
                root=merge(x,z);//重新合并 
            }
            if(u==6)//求后继 
            {
                split(root,k,x,z);//先分成两个Treap 此时k是小Treap中最大的数 
                printf("%d
    ",val[k_th(z,1)]);//后继即为大Treap中最小的数 即最左节点 
                root=merge(x,z);//重新合并 
            }
        }
        return 0;
    }
  • 相关阅读:
    Java IO2
    Java IO1 复制粘贴文件
    Java superArray2
    17杭州女子专场赛
    组队赛 A Promotions 深搜+逆向思维
    Java处理异常小试
    再谈Dijkstra算法和堆优化
    仿照JAVA vector模型写一个SuperArray
    HDU 2017女生赛04 (变形最短路)
    Gym-100712J 桶排序思想&反向思维
  • 原文地址:https://www.cnblogs.com/water-radish/p/9280878.html
Copyright © 2011-2022 走看看