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

主席树

时间:2020-01-22 22:23:48      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:维护   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

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