主席树,大家这么叫的,也不知道为什么?
算法思路:
1.先排序,离散化
2.按排名插入n个版本的线段树
3.没有修改,查询即可
由于维护的是权值的区间和,
因此只要查询版本r和l-1,做差比较即可
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int MAXN=100010; 5 struct Node{int L,R,sum;}; 6 struct Data{int x,id,rank;}; 7 bool cmp(Data A,Data B){return A.x<B.x;} 8 int rt[MAXN],cnt,n,m; 9 Node T[MAXN<<5]; 10 Data a[MAXN]; 11 void insert(int a,int&x,int L,int R) { 12 T[++cnt]=T[x],x=cnt,T[x].sum++; 13 if(L==R)return;int mid=(L+R)>>1; 14 if(a<=mid)insert(a,T[x].L,L,mid); 15 else insert(a,T[x].R,mid+1,R); 16 } 17 int query(int l,int r,int k,int L,int R){ 18 if(L==R)return L;int mid=(L+R)>>1; 19 int t=T[T[r].L].sum-T[T[l].L].sum; 20 if(k<=t)return query(T[l].L,T[r].L,k,L,mid); 21 else return query(T[l].R,T[r].R,k-t,mid+1,R); 22 } 23 int main(){ 24 scanf("%d%d",&n,&m); 25 for(int i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i; 26 sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++)a[a[i].id].rank=i; 27 for(int i=1;i<=n;i++)rt[i]=rt[i-1],insert(a[i].rank,rt[i],1,n); 28 for(int l,r,k; m--;)scanf("%d%d%d",&l,&r,&k),printf("%d ",a[query(rt[l-1],rt[r],k,1,n)].x); 29 return 0; 30 }