码迷,mamicode.com
首页 > 其他好文 > 详细

FHQ-treap模板篇

时间:2020-07-02 21:21:28      阅读:51      评论:0      收藏:0      [点我收藏+]

标签:line   while   merge   turn   ||   ==   pre   bsp   span   

完全能代替splay的完美算法!

核心操作:merge

int merge(int x,int y) {
    if(!x||!y) return x|y;
    if(rnd[x]<rnd[y]) {
        down(x);
        rs[x]=merge(rs[x],y);
        up(x);
        return x;
    } else {
        down(y);
        ls[y]=merge(x,ls[y]);
        up(y);
        return y;
    }
}

裂开:split

void split_s(int p,int k,int &x,int &y) { //按子树大小分
    if(!p) {
        x=y=0; return;
    }
    down(p);
/**/    if(siz[ls[p]]>=k) {
/**/        y=p; split_s(ls[p],k,x,ls[p]);
/**/    } else {
/**/        x=p; split_s(rs[p],k-(siz[ls[p]]+1),rs[p],y);
/**/    }
    up(p);
}
void split_k(int p,int k,int &x,int &y) { //按权值分
    if(!p) {
        x=y=0; return;
    }
    if(k>=c[p]) {
        x=p;
        split_k(rs[p],k,rs[p],y);
    } else {
        y=p;
        split_k(ls[p],k,x,ls[p]);
    }
    up(p);
}

新开节点:New

inline int New(int x) {
    c[++tot]=x; siz[tot]=1; rnd[tot]=rand();
    return x;
}

找子树第K大:kth

inline int kth(int p,int k) { //子树第k大
    while(1) {
        if(k<=siz[ls[p]]) p=ls[p];
            else {
                if(k==siz[ls[p]]+1) return p;
                k-=(siz[ls[p]]+1);
                p=rs[p];
            }
    }
}

把序列分成1-(l-1),l-r,(r+1)-n

    split(rt,l-1,x,y);
    split(y,r-l+1,y,z); //注意是r-l+1

up时注意不要算空节点(比如取max时可能存在负数)

 

FHQ-treap模板篇

标签:line   while   merge   turn   ||   ==   pre   bsp   span   

原文地址:https://www.cnblogs.com/wsfwsf/p/13226962.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!