[poj2104]kth-number(归并树求区间第k大)
复杂度:$O(nlog^3n)$
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #define MAXN 100000 using namespace std; int sorted[20][MAXN],a[MAXN]; void build(int deep,int l,int r){ if(l==r){ sorted[deep][l]=a[l]; return; } int mid=(l+r)>>1; build(deep+1,l,mid); build(deep+1,mid+1,r); int p=l,q=mid+1,k=l; while(p<=mid&&q<=r){ if(sorted[deep+1][p]<=sorted[deep+1][q]) sorted[deep][k++]=sorted[deep+1][p++]; else sorted[deep][k++]=sorted[deep+1][q++]; } while(p<=mid) sorted[deep][k++]=sorted[deep+1][p++]; while(q<=r) sorted[deep][k++]=sorted[deep+1][q++];//存储序列 } //查询某个数在区间内的rank int query(int deep,int l,int r,int tl,int tr,int k){ if(tr<l||tl>r) return 0; if(tl<=l&&r<=tr) return lower_bound(&sorted[deep][l],&sorted[deep][r]+1,k)-&sorted[deep][l]; int mid=(l+r)>>1; return query(deep+1,l,mid,tl,tr,k)+query(deep+1,mid+1,r,tl,tr,k); } int solve(int n,int tl, int tr, int k){ int l=1,r=n; while(l<r){ int mid=(l+r+1)>>1; int cnt=query(0,1,n,tl,tr,sorted[0][mid]); if(cnt<=k) l=mid; else r=mid-1; } return sorted[0][l]; } int main(){ int n,m; scanf("%d%d", &n, &m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(0,1,n); while(m--){ int tl,tr,k; scanf("%d%d%d", &tl, &tr, &k); printf("%d\n", solve(n,tl,tr,k-1)); } return 0; }