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

树套树

时间:2020-01-22 22:07:46      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:inf   通过   class   add   mod   区间   ++i   单点   lse   

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

支持操作

① 查询\(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;

树套树

标签:inf   通过   class   add   mod   区间   ++i   单点   lse   

原文地址:https://www.cnblogs.com/lhm-/p/12229618.html

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