昨天在写带修改主席树的时候,咸鱼zcysky发现自己似乎根本不会写主席树
于是正好找个空复习下……
主席树的原理不用我扯了,主席树为啥能求k大,大概在它可以用历史版本存下区间的前缀和,求的时候差分下就能提出我要求的区间。
不过这么搞的话不要忘了离散化。
就是上面的裸题,不要手贱写bits就好。
1 #include<iostream> 2 #include<cstdio> 3 #define N 100010 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 struct Node{int sum,ls,rs;}T[N*20]; 8 int cnt; 9 void ins(int &num,int &x,int l,int r){ 10 T[cnt++]=T[x];x=cnt-1;T[x].sum++; 11 if(l==r)return; 12 int mid=(l+r)/2; 13 if(num<=mid)ins(num,T[x].ls,l,mid); 14 else ins(num,T[x].rs,mid+1,r); 15 } 16 int query(int i,int j,int k,int l,int r){ 17 if(l==r)return l; 18 int t=T[T[j].ls].sum-T[T[i].ls].sum; 19 int mid=(l+r)/2; 20 if(k<=t)return query(T[i].ls,T[j].ls,k,l,mid); 21 else return query(T[i].rs,T[j].rs,k-t,mid+1,r); 22 } 23 struct A{ 24 int x,idx; 25 bool operator<(const A &s)const{ 26 return x<s.x;} 27 }; 28 A a[N]; 29 int rank[N],root[N]; 30 int n,m; 31 int main(){ 32 T[0].ls=T[0].rs=T[0].sum=0;root[0]=0; 33 while(scanf("%d%d",&n,&m)!=EOF){ 34 for(register int i=1;i<=n;++i){ 35 scanf("%d",&a[i].x); 36 a[i].idx=i; 37 } 38 sort(a+1,a+n+1); 39 for(int i=1;i<=n;i++)rank[a[i].idx]=i; 40 cnt=1; 41 for(int i=1;i<=n;i++){ 42 root[i]=root[i-1]; 43 ins(rank[i],root[i],1,n); 44 } 45 while(m--){ 46 int i,j,k; 47 scanf("%d%d%d",&i,&j,&k); 48 int ans=a[query(root[i-1],root[j],k,1,n)].x; 49 printf("%d\n",ans); 50 } 51 } 52 return 0; 53 }