zoukankan      html  css  js  c++  java
  • 【模板】可持久化平衡树

    传送门

    Description

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):

    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
    6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)

    和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)

    每个版本的编号即为操作的序号(版本0即为初始状态,空树)

    Solution

    当然是可持久化fhq啦

    Wa了好久,原来是没有注意到删数时,如果没有这个操作,要忽略它

    动态加点就和可持久化线段树一样,反正是很好打


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    #define MN 500005*50
    int sz,rt[MN];
    int val[MN],pri[MN],ls[MN],rs[MN],siz[MN];
    unsigned int myrand()
    {
        static unsigned int x=23333;
        return x^=x<<13,x^=x>>17,x^=x<<5;
    }
    inline void combine(int x){siz[x]=1+siz[ls[x]]+siz[rs[x]];}
    int NewNode(int x)
    {
    	++sz;
    	val[sz]=val[x];pri[sz]=pri[x];ls[sz]=ls[x];
    	rs[sz]=rs[x];siz[sz]=siz[x];
    	return sz;
    }
    int Merge(int rt1,int rt2)
    {
        if(!rt1||!rt2) return rt2|rt1;
        if(pri[rt1]<pri[rt2])
        {
        	register int p=NewNode(rt1);
            rs[p]=Merge(rs[rt1],rt2);
            combine(p);return p;
    	}
        else
        {
        	register int p=NewNode(rt2);
            ls[p]=Merge(rt1,ls[rt2]);
            combine(p);return p;
        }
    }
    void Split(int x,int k,int&rt1,int&rt2)
    {
        if(!x) return (void)(rt1=rt2=0);
        if(k<=siz[ls[x]])
        {
        	rt2=NewNode(x);
            Split(ls[x],k,rt1,ls[rt2]);
            combine(rt2);
        }
        else
        {
        	rt1=NewNode(x);
            Split(rs[x],k-siz[ls[x]]-1,rs[rt1],rt2);
            combine(rt1);
        }
    }
    int Rank(int x,int v)
    {
        if(!x) return 0;
        if(v<val[x]) return Rank(ls[x],v);
        else return siz[ls[x]]+Rank(rs[x],v)+1;
    }
    int Kth(int &root,int k)
    {
        register int rt1,rt2,rt3,c;
        Split(root,k,rt1,rt2);Split(rt1,k-1,rt3,c);
        root=Merge(rt3,Merge(c,rt2));
        return val[c];
    }
    void Insert(int &root,int v)
    {
        val[++sz]=v;pri[sz]=myrand(),siz[sz]=1;
        register int rk=Rank(root,v),rt1,rt2,c=sz;
        Split(root,rk,rt1,rt2);
        root=Merge(Merge(rt1,c),rt2);
    }
    void Delete(int &root,int v)
    {
        register int rk=Rank(root,v),rt1,rt2,rt3,c;
        Split(root,rk,rt1,rt2);Split(rt1,rk-1,rt3,c);
        if(val[c]!=v){root=Merge(Merge(rt3,c),rt2);return;}
        root=Merge(rt3,rt2);
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    //	freopen("testdata.out","w",stdout);
        register int m=read(),v,opt,x,i;
        Insert(rt[0],2147483647);Insert(rt[0],-2147483647);
        for(i=1;i<=m;++i)
        {
            v=read(),opt=read(),x=read();rt[i]=rt[v];
            switch(opt)
            {
            	case 1: Insert(rt[i],x);break;
            	case 2: Delete(rt[i],x);break;
            	case 3: printf("%d
    ",Rank(rt[i],x-1));break;
            	case 4: printf("%d
    ",Kth(rt[i],x+1));break;
            	case 5: printf("%d
    ",Kth(rt[i],Rank(rt[i],x-1)));break;
            	case 6: printf("%d
    ",Kth(rt[i],Rank(rt[i],x)+1));break;
            }
        }
        return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)
    【CityHunter】游戏流程设计及技术要点
    lua table操作
    python线程池(转)
    windows通过企业内部授权服务器激活方法
    贝叶斯定理(转)
    python 日期计算
    python 过滤 b'及提取 cmd命令返回值
    python 连接MySQL数据库
    python 获取昨天的日期
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10189918.html
Copyright © 2011-2022 走看看