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即为初始状态,空树)

    输入输出格式

    输入格式:

     

    第一行包含一个正整数N,表示操作的总数。

    接下来每行包含三个正整数,第 i 行记为 vi,opti,xi

    vi表示基于的过去版本号( 0vi<i ),opti 表示操作的序号( 1opt6 ), xi 表示参与操作的数值

     

    输出格式:

     

    每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案

     

    输入输出样例

    输入样例#1: 
    10
    0 1 9
    1 1 3
    1 1 10
    2 4 2
    3 3 9
    3 1 2
    6 4 1
    6 2 9
    8 6 3
    4 5 8
    输出样例#1: 
    9
    1
    2
    10
    3

    说明

    数据范围:

    对于28%的数据满足: 1n10

    对于44%的数据满足: 1n2102

    对于60%的数据满足: 1n3103

    对于84%的数据满足: 1n105

    对于92%的数据满足: 1n2105

    对于100%的数据满足:1n5105 , 109xi109

    经实测,正常常数的可持久化平衡树均可通过,请各位放心

    样例说明:

    共10次操作,11个版本,各版本的状况依次是:

    1. [][]

    2. [9][9]

    3. [3, 9][3,9]

    4. [9, 10][9,10]

    5. [3, 9][3,9]

    6. [9, 10][9,10]

    7. [2, 9, 10][2,9,10]

    8. [2, 9, 10][2,9,10]

    9. [2, 10][2,10]

    10. [2, 10][2,10]

    11. [3, 9][3,9]

    Solution:

      本题可持久化平衡树板子题(没啥好写的)。

      我们先用无旋treap打下普通平衡树那道板子题,那么可持久化无非是在之前版本的状态基础上每次新开节点记录新的状态就好了。

      于是只需要每次改为新建节点去merge,改为新建节点去split,记录每个版本的树根就好了(感觉很简单啊)

    代码:

    /*Code by 520 -- 9.26*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=5e5+5,inf=0x7fffffff;
    int n,root[N],cnt;
    struct node{
        int ls,rs,siz,date,rnd;
    }t[N*50];
    
    int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-') x=getchar();
        if(x=='-') x=getchar(),f=1;
        while(x>='0'&&x<='9') a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return f?-a:a;
    }
    
    il int newnode(int v){
        ++cnt;
        t[cnt].date=v,t[cnt].siz=1,t[cnt].rnd=rand();
        return cnt;    
    }
    
    il void up(int rt){t[rt].siz=t[t[rt].ls].siz+t[t[rt].rs].siz+1;}
    
    int merge(int x,int y){
        if(!x||!y) return x+y;
        if(t[x].rnd<t[y].rnd){
            int p=++cnt;t[p]=t[x];
            t[p].rs=merge(t[p].rs,y);
            up(p);
            return p;
        }
        else {
            int p=++cnt;t[p]=t[y];
            t[p].ls=merge(x,t[p].ls);
            up(p);
            return p;
        }
    }
    
    void split(int rt,int k,int &x,int &y){
        if(!rt) {x=y=0;return;}
        if(t[rt].date<=k){
            x=++cnt;t[x]=t[rt];
            split(t[x].rs,k,t[x].rs,y);
            up(x);
        }
        else {
            y=++cnt;t[y]=t[rt];
            split(t[y].ls,k,x,t[y].ls);
            up(y);
        }
    }
    
    void del(int &root,int v){
        int x=0,y=0,z=0;
        split(root,v,x,z),split(x,v-1,x,y);
        y=merge(t[y].ls,t[y].rs);
        root=merge(x,merge(y,z));
    }
    
    void ins(int &root,int v){
        int x=0,y=0; split(root,v,x,y);
        root=merge(x,merge(newnode(v),y));
    }
    
    il int kth(int rt,int v){
        while(1){
            if(v<=t[t[rt].ls].siz) rt=t[rt].ls;
            else if(v>t[t[rt].ls].siz+1) v-=t[t[rt].ls].siz+1,rt=t[rt].rs;
            else return t[rt].date;
        }
    }
    
    il int id(int &root,int v){
        int x=0,y=0,ans; split(root,v-1,x,y);
        ans=t[x].siz+1;
        root=merge(x,y);
        return ans;
    }
    
    il int pre(int &root,int v){
        int x=0,y=0,ans; split(root,v-1,x,y);
        if(!x) return -inf;
        ans=kth(x,t[x].siz);
        root=merge(x,y);
        return ans;
    }
    
    il int suc(int &root,int v){
        int x=0,y=0,ans; split(root,v,x,y);
        if(!y) return inf;
        ans=kth(y,1);
        root=merge(x,y);
        return ans;
    }
    
    int main(){
        srand(time(0));
        n=gi();
        int v,opt,x;
        For(i,1,n){
            v=gi(),opt=gi(),x=gi();
            root[i]=root[v];
            if(opt==1) ins(root[i],x);
            if(opt==2) del(root[i],x);
            if(opt==3) printf("%d
    ",id(root[i],x));
            if(opt==4) printf("%d
    ",kth(root[i],x));
            if(opt==5) printf("%d
    ",pre(root[i],x));
            if(opt==6) printf("%d
    ",suc(root[i],x));
        }
        return 0;
    }
  • 相关阅读:
    第一节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
    Tensorflow 错误:Unknown command line flag 'f'
    Python 多线程总结
    Git 强制拉取覆盖本地所有文件
    Hive常用函数 傻瓜学习笔记 附完整示例
    Linux 删除指定大小(范围)的文件
    Python 操作 HBase —— Trift Trift2 Happybase 安装使用
    梯度消失 梯度爆炸 梯度偏置 梯度饱和 梯度死亡 文献收藏
    Embedding 文献收藏
    深度学习在CTR预估中的应用 文献收藏
  • 原文地址:https://www.cnblogs.com/five20/p/9721208.html
Copyright © 2011-2022 走看看