主席树
Posted kamimxr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主席树相关的知识,希望对你有一定的参考价值。
我们一开始要建一棵空线段树,然后一个一个的添加线段树。加入线段树后会是这样:
再加入[1,
至此,裸树就建好了,并且只用了O(nlogn)的空间。
查询的时候存两个点,一开始为两个区间的根结点,两结点的差比大小,两个点要同时往左/右跳。
#include <bits/stdc++.h> using namespace std; int n,q,m; int a[200010],b[200010]; int root[20001000]; int size[20001000]; int cnt; int L[20000100],R[20001000]; int build(int l,int r) int rt=++cnt; size[rt]=0; if(l==r) return rt; int mid=(l+r)/2; L[rt]=build(l,mid); R[rt]=build(mid+1,r); return rt; int add(int pre,int l,int r,int goal) int rt=++cnt; size[rt]=size[pre]+1; L[rt]=L[pre]; R[rt]=R[pre]; if(l==r) return rt; int mid=(l+r)/2; if(goal<=mid) L[rt]=add(L[pre],l,mid,goal); else R[rt]=add(R[pre],mid+1,r,goal); return rt; int query(int u,int v,int l,int r,int goal) if(l>=r) return l; int tmp=size[L[v]]-size[L[u]]; int mid=(l+r)/2; if(tmp>=goal) return query(L[u],L[v],l,mid,goal); else return query(R[u],R[v],mid+1,r,goal-tmp); int main () scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]); b[i]=a[i]; sort(b+1,b+1+n); m=unique(b+1,b+1+n)-b-1; root[0]=build(1,m); for(int i=1;i<=n;i++) int tmp=lower_bound(b+1,b+1+m,a[i])-b; root[i]=add(root[i-1],1,m,tmp); for(int i=1;i<=q;i++) int x,y,z; scanf("%d%d%d",&x,&y,&z); int tmp=query(root[x-1],root[y],1,m,z); printf("%d\\n",b[tmp]);
以上是关于主席树的主要内容,如果未能解决你的问题,请参考以下文章