标签:维护 lse 相减 pre odi 节点 查询 次数 line
主席树节点中维护的值,是\([x,y]\)之间这个区间内数字出现了的次数
利用可持久化线段树的性质来进行查询,如查询区间\([2,5]\),即将版本五和版本一对应节点相减,即为\([2, 5]\)内某个范围内的数字的个数
对于一个区间\([l, r]\),每次算出在\([l, mid]\)范围内的数字个数,如果数量$ \geqslant k \((\)k\(就是第\)k$小),就去查询左子树,否则就去查询右子树
\(code :\)
void build(int L,int R,int &cur)
{
cur=++tree_cnt;
if(L==R) return;
int mid=(L+R)>>1;
build(L,mid,ls[cur]);
build(mid+1,R,rs[cur]);
}
void modify(int L,int R,int pos,int pre,int &cur)
{
cur=++tree_cnt;
ls[cur]=ls[pre],rs[cur]=rs[pre];
val[cur]=val[pre]+1;
if(L==R) return;
int mid=(L+R)>>1;
if(pos<=mid) modify(L,mid,pos,ls[pre],ls[cur]);
if(pos>mid) modify(mid+1,R,pos,rs[pre],rs[cur]);
}
int query(int L,int R,int x,int y,int rnk)
{
if(L==R) return L;
int num=val[ls[y]]-val[ls[x]],mid=(L+R)>>1;
if(num>=rnk) return query(L,mid,ls[x],ls[y],rnk);
else return query(mid+1,R,rs[x],rs[y],rnk-num);
}
......
build(1,n,root[0]);
for(int i=1;i<=n;++i) modify(1,n,a[i],root[i-1],root[i]);//建树
rev[query(1,n,root[l-1],root[r],k)]//查询
标签:维护 lse 相减 pre odi 节点 查询 次数 line
原文地址:https://www.cnblogs.com/lhm-/p/12229518.html