树套树
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;
以上是关于树套树的主要内容,如果未能解决你的问题,请参考以下文章