树套树

Posted lhm-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树套树相关的知识,希望对你有一定的参考价值。

在一个树形数据结构上的每个节点都是一个树形数据结构

支持操作

① 查询(k)在区间内的排名(通过线段树来合并区间来统计答案)

② 查询区间内排名为(k)的值(通过二分实现,用查询排名来(check)

③ 修改某一位值上的数值(线段树单点修改,同时更新平衡树)

④ 查询(k)在区间内的前驱(通过线段树来合并区间来统计答案)

⑤ 查询(k)在区间内的后继(通过线段树来合并区间来统计答案)

线段树套(FHQ Treap)

(code:)

struct FHQ_Treap
{
    int root,x,y,z;
    int add(int x)
    {
        val[++tot]=x;
        siz[tot]=1;
        key[tot]=rand();
        return tot;
    }
    void pushup(int x)
    {
        siz[x]=siz[ls[x]]+siz[rs[x]]+1;
    }
    void merge(int &p,int x,int y)
    {
        if(!x||!y)
        {   
            p=x+y;
            return;
        }
        if(key[x]<key[y]) p=x,merge(rs[p],rs[p],y);
        else p=y,merge(ls[p],x,ls[p]);
        pushup(p);
    }
    void split(int p,int k,int &x,int &y)
    {
        if(!p)
        {
            x=y=0;
            return;
        }
        if(val[p]<=k) x=p,split(rs[p],k,rs[p],y);
        else y=p,split(ls[p],k,x,ls[p]);
        pushup(p);
    }
    void insert(int v)
    {
        split(root,v,x,y);
        merge(x,x,add(v));
        merge(root,x,y);
    }
    void del(int v)
    {
        split(root,v,x,y);
        split(x,v-1,x,z);
        merge(z,ls[z],rs[z]);
        merge(x,x,z);
        merge(root,x,y);
    }
    void build(int l,int r)
    {
        for(int i=l;i<=r;++i) insert(a[i]);
    }
    int kth(int v)
    {
        split(root,v-1,x,y);
        int ans=siz[x]+1;
        merge(root,x,y);
        return ans;
    }
    int get(int p,int k)
    {
        if(k==siz[ls[p]]+1) return val[p];
        if(k<=siz[ls[p]]) return get(ls[p],k);
        else return get(rs[p],k-siz[ls[p]]-1);
    }
    int pre(int v)
    {
        split(root,v-1,x,y);
        int ans;
        if(siz[x]) ans=get(x,siz[x]);
        else ans=-inf;
        merge(root,x,y);
        return ans;
    }
    int nxt(int v)
    {
        split(root,v,x,y);
        int ans;
        if(siz[y]) ans=get(y,1);
        else ans=inf;
        merge(root,x,y);
        return ans;
    }
}treap[maxn];
struct Segment_Tree
{
    void build(int l,int r,int &cur)
    {
        cur=++tree_cnt;
        treap[cur].build(l,r);
        if(l==r) return;
        int mid=(l+r)>>1;
        build(l,mid,lc[cur]),build(mid+1,r,rc[cur]);
    }
    int q_rnk(int L,int R,int l,int r,int k,int cur)
    {
        if(L<=l&&R>=r)  return treap[cur].kth(k)-1;
        int mid=(l+r)>>1,ans=0;
        if(L<=mid) ans+=q_rnk(L,R,l,mid,k,lc[cur]);
        if(R>mid) ans+=q_rnk(L,R,mid+1,r,k,rc[cur]);
        return ans;
    }
    int q_val(int L,int R,int rnk)
    {
        int l=0,r=1e8,ans;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(q_rnk(L,R,1,n,mid,root)+1<=rnk) ans=mid,l=mid+1;
            else r=mid-1;
        }
        return ans;
    }
    void modify(int l,int r,int pos,int k,int cur)
    {
        treap[cur].del(a[pos]),treap[cur].insert(k);
        if(l==r) return;
        int mid=(l+r)>>1;
        if(pos<=mid) modify(l,mid,pos,k,lc[cur]);
        if(pos>mid) modify(mid+1,r,pos,k,rc[cur]);
    }
    int lower(int L,int R,int l,int r,int k,int cur)
    {
        if(L>r||R<l) return -inf;
        if(L<=l&&R>=r) return treap[cur].pre(k);
        int mid=(l+r)>>1;
        return max(lower(L,R,l,mid,k,lc[cur]),lower(L,R,mid+1,r,k,rc[cur]));
    }
    int upper(int L,int R,int l,int r,int k,int cur)
    {
        if(L>r||R<l) return inf;
        if(L<=l&&R>=r) return treap[cur].nxt(k);
        int mid=(l+r)>>1;
        return min(upper(L,R,l,mid,k,lc[cur]),upper(L,R,mid+1,r,k,rc[cur]));
    }
}tree;

以上是关于树套树的主要内容,如果未能解决你的问题,请参考以下文章

「模板」 树套树

树套树三题 题解

模板二逼平衡树(树套树)

P3380 模板二逼平衡树(树套树)

[BZOJ 720][JZYZOJ 2016]gty的妹子树 强制在线 树分块/树套树

树套树-线段树套平衡树