graph TD
A["[1,8]: arr=[4,2,7,1,5,3,8,6]\nB=[0,1,1,1,2,2,3,3]"] --> B["[1,4]: arr=[4,2,1,3]\nB=[0,0,1,2]"]
A --> C["[5,8]: arr=[7,5,8,6]\nB=[0,0,1,1]"]
B --> D["[1,2]: arr=[2,1]\nB=[0,1]"]
B --> E["[3,4]: arr=[4,3]\nB=[0,0]"]
C --> F["[5,6]: arr=[5,6]\nB=[0,1]"]
C --> G["[7,8]: arr=[7,8]\nB=[0,0]"]
D --> H["[1,1]: 1"]
D --> I["[2,2]: 2"]
E --> J["[3,3]: 3"]
E --> K["[4,4]: 4"]
F --> L["[5,5]: 5"]
F --> M["[6,6]: 6"]
G --> N["[7,7]: 7"]
G --> O["[8,8]: 8"]
Trace: Tìm phần tử nhỏ thứ 3 trong \([0, 7]\) (toàn mảng)¶
#include<bits/stdc++.h>usingnamespacestd;structWaveletTree{intlo,hi;vector<int>B;WaveletTree*left,*right;WaveletTree(vector<int>::iteratorfrom,vector<int>::iteratorto,intx,inty):lo(x),hi(y),left(nullptr),right(nullptr){if(from==to||lo==hi)return;intmid=(lo+hi)/2;autof=[mid](intx){returnx<=mid;};B.reserve(to-from+1);B.push_back(0);for(autoit=from;it!=to;it++)B.push_back(B.back()+f(*it));autopivot=stable_partition(from,to,f);left=newWaveletTree(from,pivot,lo,mid);right=newWaveletTree(pivot,to,mid+1,hi);}// Số phần tử <= k trong [l, r] (1-indexed)intcountLessEq(intl,intr,intk){if(l>r||k<lo)return0;if(hi<=k)returnr-l+1;intlb=B[l-1],rb=B[r];returnleft->countLessEq(lb+1,rb,k)+right->countLessEq(l-lb,r-rb,k);}// Phần tử nhỏ thứ k trong [l, r] (1-indexed)intkth(intl,intr,intk){if(lo==hi)returnlo;intlb=B[l-1],rb=B[r];intinLeft=rb-lb;if(k<=inLeft)returnleft->kth(lb+1,rb,k);elsereturnright->kth(l-lb,r-rb,k-inLeft);}~WaveletTree(){deleteleft;deleteright;}};intmain(){ios_base::sync_with_stdio(false);cin.tie(NULL);intn,q;cin>>n>>q;vector<int>a(n);for(inti=0;i<n;i++)cin>>a[i];intminVal=*min_element(a.begin(),a.end());intmaxVal=*max_element(a.begin(),a.end());WaveletTreewt(a.begin(),a.end(),minVal,maxVal);while(q--){inttype;cin>>type;if(type==1){intl,r,k;cin>>l>>r>>k;cout<<wt.kth(l,r,k)<<"\n";}else{intl,r,x;cin>>l>>r>>x;cout<<wt.countLessEq(l,r,x)<<"\n";}}return0;}
# Wavelet Tree trong Python (chỉ dùng cho mục đích học tập)# Với N lớn, nên dùng C++ vì Wavelet Tree tốn nhiều bộ nhớ trong PythonclassWaveletTree:def__init__(self,data,lo,hi):self.lo=loself.hi=hiself.B=[0]self.left=self.right=Noneiflo==hiornotdata:returnmid=(lo+hi)//2self.B=[0]forxindata:self.B.append(self.B[-1]+(1ifx<=midelse0))left_data=[xforxindataifx<=mid]right_data=[xforxindataifx>mid]self.left=WaveletTree(left_data,lo,mid)self.right=WaveletTree(right_data,mid+1,hi)defkth(self,l,r,k):ifself.lo==self.hi:returnself.loin_left=self.B[r]-self.B[l-1]ifk<=in_left:new_l=self.B[l-1]+1new_r=self.B[r]returnself.left.kth(new_l,new_r,k)else:new_l=l-self.B[l-1]new_r=r-self.B[r]returnself.right.kth(new_l,new_r,k-in_left)n,q=map(int,input().split())a=list(map(int,input().split()))lo,hi=min(a),max(a)wt=WaveletTree(a,lo,hi)for_inrange(q):parts=list(map(int,input().split()))ifparts[0]==1:l,r,k=parts[1],parts[2],parts[3]print(wt.kth(l,r,k))