[Cpp]
/*
Returns the median value of the interval.
Can be converted to the kth value, so the partition tree is used.
Directly applied the previous function
Explained in the previous article
*/
# 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; // obtain the middle
Int midd = srted [mid];
Int same = mid-l + 1, samed = 0, zn = L-1, yn = mid, I; // The number of left child elements first recognized by same
// The following is less than midd (it will definitely enter the left child). The remaining is = midd and the number of left children is to be entered.
// Samed indicates the number of inserts.
// Zn and yn are the starting positions of the left and right children-1. The elements are allocated to the areas of the two children.
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 one with the same front and side.
{
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 by 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 quota has not been used up.
{
++ Samed;
++ T [d]. num [I];
T [d + 1]. val [+ zn] = t [d]. val [I];
} Else // you have 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 [, k branch in B]
{
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) // [a, B] elements entering the left subtree> = k
Return 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); // find the large elements in the front (sy-sx) in the left subtree in the right subtree.
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;
}
}
}
Author: qq172108805