标签:return main src ace math XML 主席树 height add
我们一开始要建一棵空线段树,然后一个一个的添加线段树。加入线段树后会是这样:
再加入[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]); } }
标签:return main src ace math XML 主席树 height add
原文地址:https://www.cnblogs.com/kamimxr/p/11271945.html