zoukankan      html  css  js  c++  java
  • [洛谷P3835]【模板】可持久化平衡树

    题目大意:
    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
    6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)
    和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)
    每个版本的编号即为操作的序号(版本0即为初始状态,空树)。
    解题思路:
    可持久化平衡树,用非旋Treap实现。
    和普通Treap其实没什么区别,主要是split和平常写的重量平衡树有点不同,然后每次要新建节点,其他都一样。

    C++ Code:

    #include<bits/stdc++.h>
    #define N 500005
    struct node{
        int r,ls,rs,s,sz;
    }a[N*50];
    int rt[N],cnt=0;
    inline int readint(){
        int c=getchar(),d=0,b=0;
        for(;!isdigit(c);c=getchar())b=c=='-';
        for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0');
        return b?-d:d;
    }
    inline void update(int x){
        a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;
    }
    void split(int u,int k,int& x,int& y){
        if(!u)x=y=0;
        else{
            if(a[u].s<=k){
                a[x=++cnt]=a[u];
                split(a[x].rs,k,a[x].rs,y);
                update(x);
            }else{
                a[y=++cnt]=a[u];
                split(a[y].ls,k,x,a[y].ls);
                update(y);
            }
        }
    }
    int merge(int x,int y){
        if(!x||!y)return x|y;
        int u;
        if(a[x].r<a[y].r){
            a[u=++cnt]=a[x];
            a[u].rs=merge(a[u].rs,y);
        }else{
            a[u=++cnt]=a[y];
            a[u].ls=merge(x,a[u].ls);
        }
        update(u);
        return u;
    }
    void Insert(int& root,int w){
        int x,y,z;
        split(root,w,x,y);
        a[z=++cnt]=(node){rand(),0,0,w,1};
        root=merge(merge(x,z),y);
    }
    void Delete(int& root,int w){
        int x,y,z;
        split(root,w,x,y);
        split(x,w-1,x,z);
        if(a[z].s==w)
        root=merge(merge(x,merge(a[z].ls,a[z].rs)),y);else
        root=merge(merge(x,z),y);
    }
    int getpos(int now,int k){
        for(;;){
            if(k<=a[a[now].ls].sz)now=a[now].ls;
            if(k==a[a[now].ls].sz+1)return now;
            if(k>a[a[now].ls].sz)k-=a[a[now].ls].sz+1,now=a[now].rs;
        }
    }
    int kth(int rt,int w){
        int x,y,rank;
        split(rt,w-1,x,y);
        rank=a[x].sz+1;
        rt=merge(x,y);
        return rank;
    }
    int find(int rt,int w){
        return a[getpos(rt,w)].s;
    }
    int pre(int rt,int w){
        int x,y,ans;
        split(rt,w-1,x,y);
        if(!x)ans=-2147483647;else
        ans=a[x].sz;
        if(ans!=-2147483647)
        ans=find(x,ans);
        rt=merge(x,y);
        return ans;
    }
    int nxt(int rt,int w){
        int x,y,ans;
        split(rt,w,x,y);
        if(!y)ans=2147483647;else
        ans=a[y].sz;
        if(ans!=2147483647)
        ans=find(y,1);
        rt=merge(x,y);
        return ans;
    }
    int main(){
        srand(20170607);
        memset(rt,0,sizeof rt);
        memset(a,0,sizeof a);
        for(int T=readint(),now=1;now<=T;++now){
            int v=readint(),opt=readint(),x=readint();
            rt[now]=rt[v];
            if(opt==1)Insert(rt[now],x);else
            if(opt==2)Delete(rt[now],x);else
            if(opt==3)printf("%d
    ",kth(rt[now],x));else
            if(opt==4)printf("%d
    ",find(rt[now],x));else
            if(opt==5)printf("%d
    ",pre(rt[now],x));else
            printf("%d
    ",nxt(rt[now],x));
        }
        return 0;
    }
    
  • 相关阅读:
    mysql事务
    mysql函数
    mysql自连接
    MYSQL添加外键关联
    SQL多表查询
    SQL数据完整性
    SQL limit
    SQL分组查询
    升级GCC 6.2编译LLVM的问题
    Quartz时SLF4J错误
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8857943.html
Copyright © 2011-2022 走看看