Description
You are are working for Macrohard company in data Structures Department. After failing your previous task about key insertion you were asked to write a new data structure that would is able to re Turn quickly k-th order statistics in the array segment.
That's, given an array A[1...N] of different integer numbers, your program must answer a series of questions Q (I, J, K) in The form: "What would is the k-th number in A[I...J] segment, if this segment is sorted?"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q (2, 5, 3). The segment a[2 ... 5] is (5, 2, 6, 3). If We sort this segment, we have (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.
Input
The ' I ' input file contains n-the size of the array, and m-the number of questions to answer (1 <= n <=, 1 <= m <= 5 000).
The second line contains n different integers numbers not exceeding 10^9 by their absolute values-the array for which the Answers should be given.
The following m lines contain question descriptions, each description consists of three numbers:i, J, and K (1 <= i &L T;= j <= N, 1 <= k <= j-i + 1) and represents the question Q (I, J, K).
Output
For each question output the answer to it-the k-th number in sorted A[I...J] segment.
Sample Input
7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7-
3
Sample Output
5
6
3
the
Static query interval k small number.
train of Thought
The basic application of "dividing Tree/Chairman Tree" is attached to the following template.
AC Code Divide the tree
#include <iostream> #include <algorithm> #include <cstring> using namespace std;
typedef __int64 LL;
const int MAXN=1E5+10; int TREE[20][MAXN]; The value of each position in each layer int SORTED[MAXN]; Already sorted number int TOLEFT[20][MAXN];
The number of layers from 1-j is divided into the left void build (int l,int r,int dep) {if (l==r) return;
int mid = (l+r) >>1; int same = mid-l+1;
The number of values equal to the median and divided to the left number for (int i=l; i<=r; i++) {if (tree[dep][i]<sorted[mid)) same--;
int lpos = l;
int rpos = mid+1;
for (int i=l; i<=r; i++) {if (Tree[dep][i]<sorted[mid)) tree[dep+1][lpos++]=tree[dep][i];
else if (tree[dep][i]==sorted[mid]&&same>0) tree[dep+1][lpos++]=tree[dep][i],same--;
else Tree[dep+1][rpos++]=tree[dep][i];
Toleft[dep][i]=toleft[dep][l-1]+lpos-l;
Build (l,mid,dep+1);
Build (mid+1,r,dep+1); int query (int l,int r,int l,int r,int dep,int k) {if(L==R) return tree[dep][l];
int mid = (l+r) >>1;
int cnt = TOLEFT[DEP][R]-TOLEFT[DEP][L-1];
if (cnt>=k) {int newl = l+toleft[dep][l-1]-toleft[dep][l-1];
int newr = newl+cnt-1;
return query (L,MID,NEWL,NEWR,DEP+1,K);
else {int NEWR = R +toleft[dep][r]-toleft[dep][r];
int newl = newr-(r-l-cnt);
return query (MID+1,R,NEWL,NEWR,DEP+1,K-CNT);
int main () {Ios::sync_with_stdio (false);
int n,m;
while (cin>>n>>m) {memset (tree,0,sizeof);
for (int i=1; i<=n; i++) {cin>>tree[0][i];
Sorted[i]=tree[0][i];
Sort (sorted+1,sorted+n+1);
Build (1,n,0);
int s,t,k;
while (m--) {cin>>s>>t>>k;
Cout<<query (1,n,s,t,0,k) <<endl;
} return 0; }
President Tree
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace
Std
typedef __int64 LL;
const int MAXN = 2000000;
int A[MAXN],B[MAXN];
int SUM[MAXN];
int LS[MAXN];
int RS[MAXN];
int RK[MAXN];
int tot;
void build (int &o,int l,int r) {O=++tot;
sum[o]=0;
if (l==r) return;
int mid = (l+r) >>1;
Build (Ls[o],l,mid);
Build (Rs[o],mid+1,r);
} void Update (int &o,int l,int r,int last,int p) {o = ++tot;
Ls[o]=ls[last];
Rs[o]=rs[last];
sum[o]=sum[last]+1;
if (l==r) return;
int mid = (l+r) >>1;
if (p<=mid) update (LS[O],L,MID,LS[LAST],P);
else update (RS[O],MID+1,R,RS[LAST],P);
int query (int l,int r,int l,int r,int k) {if (l==r) return L;
int mid = (l+r) >>1;
int cnt = sum[ls[r]]-sum[ls[l]];
if (k<=cnt) return query (L,MID,LS[L],LS[R],K);
else return query (MID+1,R,RS[L],RS[R],K-CNT);
int main () {Ios::sync_with_stdio (false);
int n,m; WhIle (Cin>>n>>m) {tot=0;
for (int i=1; i<=n; i++) cin>>a[i],b[i]=a[i];
Sort (b+1,b+n+1);
int sz = unique (b+1,b+n+1)-(b+1);
Build (RK[0],1,SZ);
for (int i=1; i<=n; i++) {A[i] = Lower_bound (b+1,b+n+1,a[i))-B;
Update (rk[i],1,sz,rk[i-1],a[i]);
while (m--) {int l,r,k;
cin>>l>>r>>k;
Cout<<b[query (1,sz,rk[l-1],rk[r],k)]<<endl;
} return 0; }