• 好久不见的博客咯!——没有可持久化的可持久化treap


    每每想要去了解可持久化treap这个好写好调的东东,然后就发现网上只有一个人的——SymenYang的!在此我必须得把他批判一番——写方法不贴代码是什么心态!而且写出来的是有问题的呀!害人不浅!

    好吧说正经事,这个版本的treap名叫可持久化treap却没有可持久化,而是借鉴了可持久化treap中的一些写法。貌似可持久化之后反而难写难调。。。在这个版本的treap中加入了堆权值来维护树的形状,然后由三种操作——合并(merge),按size拆分(split_size),按值拆分(split_kth)。先说说merge。merge 这个操作是将两颗子树a,b(b中元素大于等于a中的元素)合并。这是我们这就是一个递归的过程:对于a,b中的当前节点x,y,按照他们的堆权值来确定父亲和儿子的关系,然后再往下递归这个过程,接左儿子还是右儿子看具体的值。然后split中要引入一个nodepair的结构来返回(把一棵拆成两棵得要个结构来返回啊),基本的操作跟在bst上找第k大和前k个的值一致。。具体看代码理解吧。。。 不好画图。。。。

    /*
        针对的是平衡二叉树那道入门题
    */
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
     
     
    const int maxn = 200001;
    int ans = 0;
    struct node{
        int key,data,size;
        node *son[2];
        node(){ key = rand();}
    }e[maxn],*root;int ne = 0;
     
    struct nodepair{
        node* l,*r;
    };
     
    nodepair mkpair(node* a,node* b){
        nodepair x;
        x.l = a, x.r = b;
        return x;
    }
     
    void update(node* x){
        if(x){//判断不能少!
            x->size = 1;
            if(x->son[0]) x->size += x->son[0]->size;
            if(x->son[1]) x->size += x->son[1]->size;
        }
    }
     
    node* merge(node* a,node *b){
        if(!a) {update(b);return b;}
        if(!b) {update(a);return a;}
        if(a->key <= b->key){
            a->son[1] = merge(a->son[1],b);
            update(a); return a;
        }
        else{
            b->son[0] = merge(a,b->son[0]);
            update(b); return b;
        }
    }
     
    nodepair split_size(node* a,int k){
        if(!a) return mkpair(NULL,NULL);
        if(!k) return mkpair(NULL,a);
        int ts = a->son[0] ? a->son[0]->size : 0;
        nodepair km;
        if(ts >= k){
            km = split_size(a->son[0],k);
            a->son[0] = km.r; update(a);
            return mkpair(km.l,a);
        }
        else{
            km = split_size(a->son[1],k - ts - 1);
            a->son[1] = km.l; update(a);
            return mkpair(a,km.r);
        }
    }
     
    nodepair split_kth(node* a,int k){
        if(!a) return mkpair(NULL,NULL);
        nodepair km;
        if(a->data <= k){
            km = split_kth(a->son[1],k);
            a->son[1] = km.l; update(a);
            return mkpair(a,km.r);
        }
        else{
            km = split_kth(a->son[0],k);
            a->son[0] = km.r; update(a);
            return mkpair(km.l,a);
        }
    }
     
    node* insert(int v){
        node* now = e + ne++;
        now->data = v;
        nodepair km = split_kth(root,v);
        return merge(km.l,merge(now,km.r));
    }
     
    node* del(int v){
        nodepair km1 = split_kth(root,v-1);
        nodepair km2 = split_size(km1.r,1);
        return merge(km1.l,km2.r);
    }
     
    void askkth(int k){
        node* now = root;
        while(true){
            int ts = now->son[0] ? now->son[0]->size : 0;
            if(ts + 1 == k) break;
            else{
                if(ts >= k) now = now->son[0];
                else k -= ts + 1, now = now->son[1];
            }
        }
        ans = now -> data;
    }
     
    node* askx(int v){
        nodepair km = split_kth(root,v-1);
        ans = km.l ? km.l->size+1 : 1;
        return merge(km.l,km.r);
    }
     
    node* pre(int v){
        nodepair km1 = split_kth(root,v-1);
        nodepair km2 = split_size(km1.l,km1.l->size - 1);
        ans = km2.r -> data;
        return merge(merge(km2.l,km2.r),km1.r);
    }
     
    node* sub(int v){
        nodepair km1 = split_kth(root,v);
        nodepair km2 = split_size(km1.r,1);
        ans = km2.l -> data;
        return merge(km1.l,merge(km2.l,km2.r));
    }
     
    int n;
     
    void read(){
        scanf("%d",&n);
        while(n--){
            int tmp,op;
            scanf("%d%d",&tmp,&op);
            if(tmp == 1) root = insert(op);
            if(tmp == 2) root = del(op);
            if(tmp == 3) root = askx(op);
            if(tmp == 4) askkth(op);
            if(tmp == 5) root = pre(op);
            if(tmp == 6) root = sub(op);
            if(tmp == 3 || tmp == 4 || tmp == 5 || tmp == 6) printf("%d
    ",ans);
        }
    }
     
    int main(){
        read();
        return 0;
    } 
    

     

  • 相关阅读:
    Git的Patch功能
    Android系统进程Zygote启动过程的源代码分析
    Android深入浅出之Zygote
    Android Ams浅析
    Handle机制详解
    详解Android中AsyncTask的使用
    将博客搬至CSDN
    Titanium studio安装
    Titanium studio介绍
    Android WebView useragent
  • 原文地址:https://www.cnblogs.com/ianaesthetic/p/3764260.html
Copyright © 2020-2023  润新知