主席树板子 p2104
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 using namespace std; 5 const int maxn=1e5+10; 6 int n,m,cnt,root[maxn]; 7 int b[maxn],a[maxn]; 8 struct node{int l,r,sum;}T[maxn*40]; 9 void update(int l,int r,int &x,int y,int pos) 10 { 11 //这里&的这种用法我不太清楚,大概就是能值传会root[]; 12 //这里T[++cnt]的值先从root[y](也就是上一颗树)传过来,然后再 13 //多拉出几个节点,去连接与之前的树相关的节点(同样是传值这一步操作) 14 T[++cnt]=T[y],T[cnt].sum++,x=cnt; 15 if(l==r) return; 16 int mid=(l+r)/2; 17 if(mid>=pos) update(l,mid,T[x].l,T[y].l,pos); 18 else update(mid+1,r,T[x].r,T[y].r,pos); 19 } 20 int query(int l,int r,int x,int y,int pos) 21 { 22 if(l==r) return l; 23 int mid=l+r>>1; 24 //这里如果sum>=pos,证明第pos大的值就在左边了,所以只需要枚举左边; 25 //否则枚举右边; 26 int sum=T[T[y].l].sum-T[T[x].l].sum; 27 if(sum>=pos) return query(l,mid,T[x].l,T[y].l,pos); 28 //右边的操作与左边大致相同,但是需要pos-sum,把前面的数去掉, 29 //因为右数是从1重新开始计数的。 30 else return query(mid+1,r,T[x].r,T[y].r,pos-sum); 31 } 32 int main() 33 { 34 scanf("%d%d",&n,&m); 35 for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; 36 sort(b+1,b+1+n); 37 //离散化,为什么要离散化呢。因为主席树需要开的内存很大, 38 //离散化能降低内存; 39 int t=unique(b+1,b+1+n)-b-1; 40 for(int i=1;i<=n;i++){ 41 //取出离散化后的值; 42 int tmp=lower_bound(b+1,b+1+t,a[i])-b; 43 update(1,n,root[i],root[i-1],tmp); 44 } 45 for(int i=1;i<=m;i++){ 46 int x,y,k; 47 scanf("%d%d%d",&x,&y,&k); 48 //求出query后,再放进b数组,还原为之前的值。 49 printf("%d\n",b[query(1,n,root[x-1],root[y],k)]); 50 } 51 return 0; 52 }