/* The median of the interval can be converted to the kth value. Therefore, the previous function is directly applied to the partition tree. */# include <iostream> # include <algorithm> using namespace STD; const int n = 100010; int srted [N]; struct node {int num [N]; int Val [N];} t [40]; int n, m; void build (int l, int R, int d) // This tree is composed not of nodes but of arrays, for example, L ~ of layer D ~ R is a node {If (L = r) return; int mid = (L + r)> 1; // take the int MIDD = srted [Mid] in the middle; int same = mid-L + 1, samed = 0, Zn = L-1, yn = mid, I; // The same is first recognized as the number of elements of the left child. // The number of elements is smaller than that of MIDD (it will definitely enter the left child) the rest is = MIDD and the number of children to enter the left/samed is the number of inserted/Zn, and YN is the start position of the left and right children-1, the elements are divided into two children's zones. For (I = L; I <= r; ++ I) if (T [D]. val [I] <MIDD) -- same; for (I = L; I <= r; ++ I) // It is a bit like putting a large row in the back and a small row with the same front and side. Check the situation {if (I = L) T [D]. num [I] = 0; else t [D]. num [I] = T [D]. num [I-1]; If (T [D]. val [I] <MIDD) {++ T [D]. num [I]; // here is the statistics on the number of elements from L to I entering the left child. This is the data mainly used in the tree. t [d + 1]. val [+ + Zn] = T [D]. val [I];} else if (T [D]. val [I]> MIDD) // enter the right child {T [d + 1]. val [++ YN] = T [D]. val [I];} else {If (samed <same) // The number of places has not been used up in the left child. {++ samed; ++ T [D]. num [I]; t [d + 1]. val [+ + Zn] = T [D]. val [I];} else // has children T [d + 1]. val [++ YN] = T [D]. val [I] ;}} build (L, mid, D + 1); // create left and right subtree build (Mid + 1, R, D + 1 );} int query (int A, int B, int K, int L, int R, int d) // search for [, the K nth {if (a = B) Return T [d ]. Val [a]; int mid = (L + r)> 1; int SX = T [D]. num [A-1], Sy = T [D]. num [B]; If (A-1 <L) SX = 0; If (sy-SX> = k) // [, b] elements entering the left subtree> = kreturn query (L + SX, L + SY-1, K, L, mid, D + 1 ); else {int S1 = (a = 1? 0: A-l-SX); int S2 = (B-A + 1)-(sy-SX); int nk = k-(sy-SX ); // The elements in the front (sy-SX) are left in the left subtree, and return query (Mid + 1 + S1, Mid + S1 + S2, NK, mid + 1, R, D + 1) ;}} int main () {int CAS = 1; int I, a, B; while (CIN> N) {cout <"case" <CAS ++ <":" <Endl; for (I = 1; I <= N; ++ I) {CIN> srted [I]; t [0]. val [I] = srted [I];} Sort (srted + 1, srted + 1 + n); Build (1, n, 0); CIN> m; for (I = 1; I <= m; ++ I) {CIN> A> B; cout <query (A, B, (A + B) /2-A + 1, 1, n, 0) <Endl ;}}}